home *** CD-ROM | disk | FTP | other *** search
/ Cream of the Crop 26 / Cream of the Crop 26.iso / os2 / pvm34b3.zip / pvm34b3 / pvm3 / src / tdpro.c < prev    next >
C/C++ Source or Header  |  1997-08-08  |  56KB  |  2,753 lines

  1.  
  2. static char rcsid[] =
  3.     "$Id: tdpro.c,v 1.20 1997/07/02 20:27:35 pvmsrc Exp $";
  4.  
  5. /*
  6.  *         PVM version 3.4:  Parallel Virtual Machine System
  7.  *               University of Tennessee, Knoxville TN.
  8.  *           Oak Ridge National Laboratory, Oak Ridge TN.
  9.  *                   Emory University, Atlanta GA.
  10.  *      Authors:  J. J. Dongarra, G. E. Fagg, M. Fischer
  11.  *          G. A. Geist, J. A. Kohl, R. J. Manchek, P. Mucci,
  12.  *         P. M. Papadopoulos, S. L. Scott, and V. S. Sunderam
  13.  *                   (C) 1997 All Rights Reserved
  14.  *
  15.  *                              NOTICE
  16.  *
  17.  * Permission to use, copy, modify, and distribute this software and
  18.  * its documentation for any purpose and without fee is hereby granted
  19.  * provided that the above copyright notice appear in all copies and
  20.  * that both the copyright notice and this permission notice appear in
  21.  * supporting documentation.
  22.  *
  23.  * Neither the Institutions (Emory University, Oak Ridge National
  24.  * Laboratory, and University of Tennessee) nor the Authors make any
  25.  * representations about the suitability of this software for any
  26.  * purpose.  This software is provided ``as is'' without express or
  27.  * implied warranty.
  28.  *
  29.  * PVM version 3 was funded in part by the U.S. Department of Energy,
  30.  * the National Science Foundation and the State of Tennessee.
  31.  */
  32.  
  33. /*
  34.  *    tdpro.c
  35.  *
  36.  *    Entry points for messages from local tasks.
  37.  *
  38. $Log: tdpro.c,v $
  39.  * Revision 1.20  1997/07/02  20:27:35  pvmsrc
  40.  *     Fixed startup race on shmem to that a shmem task can get fully
  41.  *     configured before getting any messages.
  42.  *     This involved adding two states
  43.  *     TF_PRESHMCONN and TF_SHM.  TF_PRESHMCONN indicates that messages
  44.  *     with MM_PRIO set can be sent to a task, but regular messages are
  45.  *     queued. This allows shmem tasks to be completely configured
  46.  *     before any messages flow.  When the daemon changes the state from
  47.  *     TF_PRESHMCONN to TF_SHMCONN it calls shm_wrt_pkts to write any
  48.  *     packets that were queued before task state changed to TF_SHMCONN.
  49.  *
  50.  * Revision 1.19  1997/06/27  17:32:56  pvmsrc
  51.  * Updated for WIN32 header files & Authors.
  52.  *
  53.  * Revision 1.18  1997/06/27  16:10:01  pvmsrc
  54.  *         Spawning tasks with option PvmNoSpawnParent get the
  55.  *         parent tid set to PvmParentNotSet in spawned tasks.
  56.  *
  57.  * Revision 1.17  1997/06/24  20:39:22  pvmsrc
  58.  * Eliminated unnecessary global externs.
  59.  *
  60.  * Revision 1.16  1997/06/23  21:26:46  pvmsrc
  61.  * Added checking for master host in tm_hoster().
  62.  *     - actually check hd_hostpart instead of ht_local/ht_master indices,
  63.  *         in case freaking host table has copies/duplicates.
  64.  *         (always wear 2 condoms...  :-)
  65.  *     - return new PvmHostrNMstr error code.
  66.  *
  67.  * Revision 1.15  1997/06/16  13:41:44  pvmsrc
  68.  * assign_tasks() now passes distribution info in DM_EXEC message.
  69.  *
  70.  * Revision 1.14  1997/06/02  13:20:48  pvmsrc
  71.  * tm_shmconn() marks old task w/ TF_CLOSE
  72.  *     - so work() doesn't complain about a dead socket.
  73.  *
  74.  * Revision 1.13  1997/05/28  14:04:05  pvmsrc
  75.  * Cleaned up TM_SHMCONN() handler routine.
  76.  *     - formatted like hell, and didn't compile clean on SGI64.
  77.  *
  78.  * Revision 1.12  1997/05/27  14:45:53  pvmsrc
  79.  * Added new TM message TM_SHMCONN with routine tm_shmconn():
  80.  *     which merges records and sets TF_SHMCONN flag.
  81.  * Updated entry point in loclentry() as well:
  82.  *     to accept this type of connection.
  83.  *
  84.  * Revision 1.11  1997/05/12  20:28:22  pvmsrc
  85.  * Removed duplicate #includes...
  86.  *
  87.  * Revision 1.10  1997/05/07  21:22:12  pvmsrc
  88.  * AAAIIIEEEEEEEEE!!!!
  89.  *     - removed all static-limited string unpacking:
  90.  *         * replaced with use of:
  91.  *             upkstralloc() / PVM_FREE() (for pvmd stuff).
  92.  *             new pvmupkstralloc() / PVM_FREE() (for lpvm stuff).
  93.  *         * manual allocation of local buffers for sprintf() & packing.
  94.  *         * alternate static string arrays to replace fixed-length cases.
  95.  *         * I hope this shit works...  :-Q
  96.  *
  97.  * Revision 1.9  1997/04/30  21:26:31  pvmsrc
  98.  * SGI Compiler Warning Cleanup.
  99.  *
  100.  * Revision 1.8  1997/03/27  19:57:10  pvmsrc
  101.  * Spanked in PvmNoSpawnParent flag usage.
  102.  *     - in tm_spawn(), don't set wxp->w_ptid if PvmNoSpawnParent set.
  103.  *     - in assign_tasks(), use wxp->w_ptid as parent tid instead of
  104.  *         snarfing it from wp->wa_tid...  (Bob Hack) D-Oh...
  105.  *
  106.  * Revision 1.7  1997/02/13  15:10:05  pvmsrc
  107.  * Removed unnecessary extern for struct waitc *waitlist.
  108.  *     - now in global.h.
  109.  *
  110.  * Revision 1.6  1997/01/28  19:27:49  pvmsrc
  111.  * New Copyright Notice & Authors.
  112.  *
  113.  * Revision 1.5  1996/12/30  13:37:49  pvmsrc
  114.  * Fixed closing comment in last log entry...
  115.  *
  116.  * Revision 1.4  1996/12/20  15:02:07  pvmsrc
  117.  * Fixed missing comment end *-/ ...  D-Oh!
  118.  *
  119.  * Revision 1.3  1996/10/25  13:58:08  pvmsrc
  120.  * Replaced old #includes for protocol headers:
  121.  *     - <pvmsdpro.h>, "ddpro.h", "tdpro.h"
  122.  * With #include of new combined header:
  123.  *     - <pvmproto.h>
  124.  *
  125.  * Revision 1.2  1996/10/24  22:11:04  pvmsrc
  126.  * Moved #include "global.h" below other #include's for typing.
  127.  * Added #include <pvmtev.h> for tracing constants.
  128.  * Added extern struct Pvmtracer pvmtracer for tracer info.
  129.  * Added new tm_tracer() routine to handle tracer registration requests
  130.  *     from pvm_reg_tracer().
  131.  * In tm_conn2(), insert tracer info for tasks spawned from the shell.
  132.  *     - can't get env vars set here, so rely on mailbox for that info.
  133.  *     - use new tev_send_newtask() routine.
  134.  * In assign_tasks():
  135.  *     - replace inline trace event code with new tev_send_spntask().
  136.  *     - check trctid / outtid with > 0, not non-zero, for new case where
  137.  *         task denies external collection.
  138.  * Modified change_trace() to use new event routines:
  139.  *     - tev_send_newtask(), tev_send_spntask() & tev_send_endtask().
  140.  *
  141.  * Revision 1.1  1996/09/23  23:44:45  pvmsrc
  142.  * Initial revision
  143.  *
  144.  * Revision 1.9  1995/07/19  21:27:26  manchek
  145.  * use new function pvmnametag instead of [dts]mname
  146.  *
  147.  * Revision 1.8  1995/07/03  19:11:40  manchek
  148.  * added tickle #100
  149.  *
  150.  * Revision 1.7  1995/05/17  16:55:20  manchek
  151.  * changed global mytid to pvmmytid.
  152.  * added TM_GETOPT message class
  153.  *
  154.  * Revision 1.6  1994/10/15  19:37:46  manchek
  155.  * cast message tags for comparison as integers.
  156.  * check newhosts when deleting host.
  157.  * unset TF_FORKD if task reconnects with a different pid
  158.  *
  159.  * Revision 1.5  1994/06/21  18:30:00  manchek
  160.  * subscript arith in tmname() broke with opt
  161.  *
  162.  * Revision 1.4  1994/06/04  21:45:54  manchek
  163.  * misc
  164.  *
  165.  * Revision 1.3  1994/06/03  20:38:31  manchek
  166.  * version 3.3.0
  167.  *
  168.  * Revision 1.2  1993/11/30  15:56:23  manchek
  169.  * tm_conn() complains if it can't write t-auth file (fs full?)
  170.  *
  171.  * Revision 1.1  1993/08/30  23:26:52  manchek
  172.  * Initial revision
  173.  *
  174.  */
  175.  
  176.  
  177. #ifdef NEEDMENDIAN
  178. #include <machine/endian.h>
  179. #endif
  180. #ifdef NEEDENDIAN
  181. #include <endian.h>
  182. #endif
  183. #ifdef NEEDSENDIAN
  184. #include <sys/endian.h>
  185. #endif
  186. #ifndef WIN32 
  187. #include <rpc/types.h>
  188. #include <rpc/xdr.h>
  189. #include <sys/types.h>
  190. #include <sys/time.h>
  191. #include <sys/socket.h>
  192. #include <netinet/in.h>
  193. #else
  194. #include "..\xdr\types.h"
  195. #include "..\xdr\xdr.h"
  196. #include <sys/types.h>
  197. #include <time.h>
  198. #endif
  199.  
  200. #include <fcntl.h>
  201. #ifdef    SYSVSTR
  202. #include <string.h>
  203. #else
  204. #include <strings.h>
  205. #endif
  206. #include <errno.h>
  207. #include <stdio.h>
  208.  
  209. #include <pvm3.h>
  210. #include <pvmproto.h>
  211. #include "pvmalloc.h"
  212. #include "pmsg.h"
  213. #include "task.h"
  214. #include "host.h"
  215. #include "waitc.h"
  216. #include "listmac.h"
  217. #include "bfunc.h"
  218. #include <pvmtev.h>
  219. #include "global.h"
  220.  
  221. #ifndef    min
  222. #define    min(a,b)    ((a)<(b)?(a):(b))
  223. #endif
  224.  
  225. #ifdef    NOTMPNAM
  226. #define    TMPNAMFUN(x)    pvmtmpnam(x)
  227. #define    LEN_OF_TMP_NAM    32
  228. char *pvmtmpnam();
  229.  
  230. #else    /*NOTMPNAM*/
  231. #define    TMPNAMFUN(x)    tmpnam(x)
  232. #ifdef    L_tmpnam
  233. #define    LEN_OF_TMP_NAM    L_tmpnam
  234. #else
  235. #define    LEN_OF_TMP_NAM    64
  236. #endif
  237. #endif    /*NOTMPNAM*/
  238.  
  239.  
  240. /***************
  241.  **  Globals  **
  242.  **           **
  243.  ***************/
  244.  
  245. extern void task_dump();
  246. char *debug_flags();
  247. char *inadport_hex();
  248. void i_dump();
  249. void tev_send_newtask();
  250. void tev_send_spntask();
  251. void tev_send_endtask();
  252.  
  253. extern int pvmdebmask;                /* from pvmd.c */
  254. extern int hostertid;                /* from pvmd.c */
  255. extern struct htab *hosts;            /* from pvmd.c */
  256. extern int pvmmydsig;                /* from pvmd.c */
  257. extern int myhostpart;                /* from pvmd.c */
  258. extern int pvmmytid;                /* from pvmd.c */
  259. extern struct htab *newhosts;        /* from pvmd.c */
  260. extern int nopax;                    /* from pvmd.c */
  261. extern int pvmudpmtu;                /* from pvmd.c */
  262. extern int pvmschedtid;                /* from pvmd.c */
  263. extern int taskertid;                /* from pvmd.c */
  264. extern struct Pvmtracer pvmtracer;    /* from pvmd.c */
  265. extern int tidhmask;                /* from pvmd.c */
  266.  
  267.  
  268. /***************
  269.  **  Private  **
  270.  **           **
  271.  ***************/
  272.  
  273. int tm_addhost();
  274. int tm_config();
  275. int tm_conn2();
  276. int tm_connect();
  277. int tm_context();
  278. int tm_db();
  279. int tm_delhost();
  280. int tm_exit();
  281. int tm_getopt();
  282. int tm_halt();
  283. int tm_hoster();
  284. int tm_hostsync();
  285. int tm_mca();
  286. int tm_mstat();
  287. int tm_notify();
  288. int tm_pstat();
  289. int tm_sendsig();
  290. int tm_sched();
  291. int tm_setopt();
  292. int tm_spawn();
  293. int tm_task();
  294. int tm_tasker();
  295. int tm_tickle();
  296. int tm_tracer();
  297. int tm_shmconn();
  298.  
  299. int (*loclswitch[])() = {
  300.     tm_connect,
  301.     tm_conn2,
  302.     tm_exit,
  303.     tm_addhost,
  304.     tm_delhost,
  305.     tm_config,
  306.     tm_mstat,
  307.     tm_halt,
  308.     tm_tickle,
  309.     tm_spawn,
  310.     tm_pstat,
  311.     tm_sendsig,
  312.     tm_task,
  313.     tm_mca,
  314.     tm_notify,
  315.     tm_db,
  316.     tm_sched,
  317.     tm_tasker,
  318.     tm_hoster,
  319.     tm_tracer,
  320.     tm_hostsync,
  321.     tm_setopt,
  322.     tm_getopt,
  323.     tm_context,
  324.     tm_shmconn,
  325. };
  326.  
  327.  
  328. int
  329. loclentry(tp, mp)
  330.     struct task *tp;
  331.     struct pmsg *mp;
  332. {
  333.     int c = mp->m_tag;
  334.  
  335.     if (pvmdebmask & PDMMESSAGE) {
  336.         pvmlogprintf("loclentry() from t%x tag %s\n", mp->m_src,
  337.                 pvmnametag(c, (int *)0));
  338. /*
  339.         pvmhdump(mp->m_cfrag->fr_dat, mp->m_cfrag->fr_len, "frag: ");
  340. */
  341.     }
  342.  
  343. /*
  344.     if (mp->m_enc != 1) {
  345.         pvmlogprintf("loclentry() message from t%x with bad enc %d\n",
  346.                 tp->t_tid, mp->m_enc);
  347.         goto bail;
  348.     }
  349. */
  350.  
  351.     if (c < (int)TM_FIRST || c > (int)TM_LAST) {
  352.         pvmlogprintf("loclentry() message from t%x with bogus tag %d\n",
  353.                 tp->t_tid, c);
  354.         goto bail;
  355.     }
  356.  
  357.     if ((!(tp->t_flag & TF_CONN) && c != TM_CONNECT && c != TM_CONN2 
  358.                                  && c != TM_SHMCONN)
  359.     || ((tp->t_flag & TF_AUTH) && c != TM_CONN2)) {
  360.         pvmlogerror("loclentry() non-connect message from anon task\n");
  361.         tp->t_flag |= TF_CLOSE;
  362.         goto bail;
  363.     }
  364.  
  365.     c -= TM_FIRST;
  366.     (loclswitch[c])(tp, mp);
  367.  
  368. bail:
  369.     pmsg_unref(mp);
  370.     return 0;
  371. }
  372.  
  373.  
  374. /*    replymessage()
  375. *
  376. *    Construct reply message to sender with matching context, tag, wait id
  377. */
  378.  
  379. struct pmsg *
  380. replymessage(mp)
  381.     struct pmsg *mp;
  382. {
  383.     struct pmsg *rmp;
  384.  
  385.     if (rmp = mesg_new(0)) {
  386.         rmp->m_dst = mp->m_src;
  387.         rmp->m_ctx = mp->m_ctx;
  388.         rmp->m_tag = mp->m_tag;
  389.         rmp->m_wid = mp->m_wid;
  390.     }
  391.     return rmp;
  392. }
  393.  
  394.  
  395. /*********************************
  396.  **  Task request entry points  **
  397.  **                             **
  398.  *********************************/
  399.  
  400.  
  401. /*    tm_connect()
  402. *
  403. *    Task connecting to pvmd phase 1.
  404. *    We assign it a context, write in t-auth file to prove our ident,
  405. *    then make d-auth file for task to prove itself.
  406. *
  407. *    TM_CONNECT
  408. *    call {
  409. *        int tdprotocol        // t-d protocol number compiled into libpvm
  410. *        string authfile        // t-auth file pvmd must write
  411. *    }
  412. *    ret {
  413. *        int tdprotocol        // pvmd's td protocol version
  414. *        int acknack            // 1 if pvmd accepts connection
  415. *        string authfile        // d-auth file task must write
  416. *    }
  417. */
  418.  
  419. int
  420. tm_connect(tp, mp)
  421.     struct task *tp;
  422.     struct pmsg *mp;
  423. {
  424.     int ver;                        /* task's libpvm t-d proto version */
  425.     char authfn[LEN_OF_TMP_NAM];    /* t-auth file name */
  426.     int d;
  427.     int cc;
  428.  
  429.     if (upkint(mp, &ver) || upkstr(mp, authfn, sizeof(authfn))) {
  430.         pvmlogerror("tm_connect() bad msg format\n");
  431.         goto bail;
  432.     }
  433.  
  434.     /*
  435.     *    if protocols are not compatible, send nack
  436.     *    context will get flushed after reply is sent
  437.     */
  438.  
  439.     if (ver != TDPROTOCOL) {
  440.         pvmlogprintf("tm_connect() t-d protocol mismatch (%d/%d)\n",
  441.             ver, TDPROTOCOL);
  442.  
  443.         mp = replymessage(mp);
  444.         pkint(mp, TDPROTOCOL);
  445.         pkint(mp, 0);
  446.         pkstr(mp, "");
  447.         mp->m_flag |= MM_PRIO;
  448.         mesg_to_task(tp, mp);
  449.         pmsg_unref(mp);
  450.         goto bail;
  451.     }
  452.  
  453.     /*
  454.     *    write in t-auth file, create empty d-auth file that task
  455.     *    must write and we'll check later
  456.     */
  457.  
  458.     if ((d = open(authfn, O_WRONLY, 0)) == -1) {
  459.         pvmlogperror("tm_connect() can't open t-auth file");
  460.         goto bail;
  461.     }
  462.     cc = write(d, authfn, 1);
  463.     if (cc != 1) {
  464.         if (cc == -1)
  465.             pvmlogperror(authfn);
  466.         pvmlogerror("tm_connect() can't write t-auth file\n");
  467.     }
  468.     (void)close(d);
  469.  
  470.     tp->t_authnam = TALLOC(LEN_OF_TMP_NAM, char, "auth");
  471.     (void)TMPNAMFUN(tp->t_authnam);
  472.  
  473. #ifndef IMA_OS2
  474.     if ((tp->t_authfd = open(tp->t_authnam, O_RDONLY|O_CREAT|O_TRUNC, 0600))
  475. #else
  476.     if ((tp->t_authfd = open(tp->t_authnam, O_RDWR|O_CREAT|O_TRUNC, 0600))
  477. #endif
  478.     == -1) {
  479.         pvmlogperror("tm_connect() can't create d-auth file");
  480.         PVM_FREE(tp->t_authnam);
  481.         tp->t_authnam = 0;
  482.         goto bail;
  483.     }
  484.  
  485.     /*
  486.     *    task's turn to auth
  487.     */
  488.  
  489.     tp->t_flag |= TF_AUTH;
  490.  
  491.     mp = replymessage(mp);
  492.     pkint(mp, TDPROTOCOL);
  493.     pkint(mp, 1);
  494.     pkstr(mp, tp->t_authnam);
  495.     mp->m_flag |= MM_PRIO;
  496.     mesg_to_task(tp, mp);
  497.     pmsg_unref(mp);
  498.     return 0;
  499.  
  500. bail:
  501.     tp->t_flag |= TF_CLOSE;
  502.     return 0;
  503. }
  504.  
  505.  
  506. /*    tm_conn2()
  507. *
  508. *    Task connecting to pvmd phase 2.
  509. *    We check d-auth file and give it config info, attach to real context.
  510. *
  511. *    TM_CONN2
  512. *    call {
  513. *        int unixpid            // real pid
  514. *        int cookie            // magic cookie inherited from pvmd (or 0)
  515. *    }
  516. *    ret {
  517. *        int acknack            // 1 if pvmd accepts connection
  518. *        int tid                // task tid
  519. *        int ptid            // parent tid
  520. *        int outtid            // output dst
  521. *        int outctx
  522. *        int outtag
  523. *        int trctid            // trace dst
  524. *        int trcctx
  525. *        int trctag
  526. *        int udpmax
  527. *        int nativecode
  528. *        string inaddr
  529. *        int schedtid        // scheduler tid
  530. *    }
  531. */
  532.  
  533. int
  534. tm_conn2(tp, mp)
  535.     struct task *tp;
  536.     struct pmsg *mp;
  537. {
  538.     int tid;
  539.     int pid;                        /* real pid of task */
  540.     int cookie;                        /* cookie to identify task or 0 */
  541.     struct task *tp2;                /* to search for existing context */
  542.     struct pmsg *mp2;
  543.     int cc;
  544.     char c;
  545.  
  546.     if (upkint(mp, &pid) || upkint(mp, &cookie)) {
  547.         pvmlogerror("tm_conn2() bad msg format\n");
  548.         goto bail;
  549.     }
  550.     if (!cookie)
  551.         cookie = pid;
  552.  
  553.     if (!(tp->t_flag & TF_AUTH)) {
  554.         pvmlogprintf("tm_conn2() message from t%x, TF_AUTH not set\n",
  555.                 tp->t_tid);
  556.         return 0;
  557.     }
  558.  
  559.     /*
  560.     *    check that task could write d-auth file
  561.     */
  562.  
  563.     if ((cc = read(tp->t_authfd, &c, 1)) == -1) {
  564.         pvmlogperror("tm_conn2() can't read d-auth file");
  565.         return 0;
  566.     }
  567.  
  568.     if (cc != 1) {
  569.         pvmlogerror("tm_conn2() task didn't validate itself\n");
  570.         goto bail;
  571.     }
  572.  
  573.     (void)close(tp->t_authfd);
  574.     tp->t_authfd = -1;
  575.     (void)unlink(tp->t_authnam);
  576.     PVM_FREE(tp->t_authnam);
  577.     tp->t_authnam = 0;
  578.  
  579.     /*
  580.     *    if task spawned by us, already has a context,
  581.     *    else make it one
  582.     */
  583.  
  584.     if ((tp2 = task_findpid(cookie)) && !(tp2->t_flag & (TF_AUTH|TF_CONN))) {
  585.         if (pvmdebmask & PDMTASK) {
  586.             pvmlogprintf("tm_conn2() reconnect task t%x\n", tp2->t_tid);
  587.         }
  588.         tp->t_sched = tp2->t_sched;
  589.  
  590.     } else {
  591.         if ((tid = tid_new()) < 0) {
  592.             pvmlogerror("tm_conn2() out of tids?\n");
  593.             goto bail;        /* XXX should disconnect nicely */
  594.         }
  595.         tp2 = task_new(tid);
  596.  
  597.         if (pvmschedtid) {
  598.             /* inform the scheduler about the new task */
  599.  
  600.             tp->t_sched = pvmschedtid;
  601.             mp2 = mesg_new(0);
  602.             pkint(mp2, 1);
  603.             pkint(mp2, tid);
  604.             mp2->m_tag = SM_EXECACK;        /* XXX yecch, overload */
  605.             mp2->m_dst = pvmschedtid;
  606.             sendmessage(mp2);
  607.         }
  608.  
  609.         /* check for tracer */
  610.         if (pvmtracer.trctid && pvmtracer.trctag) {
  611.             tp2->t_trctid = pvmtracer.trctid;
  612.             tp2->t_trcctx = pvmtracer.trcctx;
  613.             tp2->t_trctag = pvmtracer.trctag;
  614.             /* Note:  can't get the trace mask or trace buffer size
  615.                 to task here, but this will be handled using mailbox */
  616.  
  617.             /* trace start message */
  618.             /* XXX Note:  we don't really know if we should send this
  619.                 because this task could have prohibited tracing
  620.                 by setting PvmSelfTraceTid to -1... */
  621.             tev_send_newtask(
  622.                 pvmtracer.trctid, pvmtracer.trcctx, pvmtracer.trctag,
  623.                 tid, -1, -1, "-" );
  624.         }
  625.         if (pvmtracer.outtid && pvmtracer.outtag) {
  626.             tp2->t_outtid = pvmtracer.outtid;
  627.             tp2->t_outctx = pvmtracer.outctx;
  628.             tp2->t_outtag = pvmtracer.outtag;
  629.  
  630.             /* output start message */
  631.             /* Note:  same deal here as for TEV_NEWTASK above... */
  632.             mp2 = mesg_new(0);
  633.             mp2->m_dst = pvmtracer.outtid;
  634.             mp2->m_ctx = pvmtracer.outctx;
  635.             mp2->m_tag = pvmtracer.outtag;
  636.             pkint(mp2, tid);
  637.             pkint(mp2, -2);
  638.             pkint(mp2, -1);
  639.             sendmessage(mp2);
  640.         }
  641.  
  642.         if (pvmdebmask & PDMTASK) {
  643.             pvmlogprintf("tm_conn2() new task t%x\n", tp2->t_tid);
  644.         }
  645.     }
  646.  
  647.     /*
  648.     *    brundle-fly the contexts together
  649.     */
  650.  
  651.     tp2->t_sock = tp->t_sock;
  652.     tp2->t_sad = tp->t_sad;
  653.     tp2->t_salen = tp->t_salen;
  654.     if (tp2->t_pid != pid)
  655.         task_setpid(tp2, pid);
  656.     tp2->t_rxp = tp->t_rxp;
  657.     tp2->t_sched = tp->t_sched;
  658.     tp->t_sock = -1;    /* tp will be freed by loclinput() */
  659.     tp->t_rxp = 0;
  660.     tp = tp2;
  661.     if (cookie != pid)
  662.         tp->t_flag &= ~TF_FORKD;
  663.  
  664.     /*
  665.     *    kick it in the butt; it's ready to go
  666.     */
  667.  
  668.     tp->t_flag &= ~TF_AUTH;
  669.     tp->t_flag |= TF_CONN;
  670.  
  671.     mp = replymessage(mp);
  672.     pkint(mp, 1);
  673.     pkint(mp, tp->t_tid);
  674.     pkint(mp, tp->t_ptid);
  675.     pkint(mp, tp->t_outtid);
  676.     pkint(mp, tp->t_outctx);
  677.     pkint(mp, tp->t_outtag);
  678.     pkint(mp, tp->t_trctid);
  679.     pkint(mp, tp->t_trcctx);
  680.     pkint(mp, tp->t_trctag);
  681.     pkint(mp, pvmudpmtu);
  682.     pkint(mp, pvmmydsig);
  683.     pkstr(mp, inadport_hex(&(hosts->ht_hosts[hosts->ht_local]->hd_sad)));
  684.     pkint(mp, pvmschedtid);
  685.     mp->m_dst = tp->t_tid;
  686.     mp->m_flag |= MM_PRIO;
  687.     sendmessage(mp);
  688.     return 0;
  689.  
  690. bail:
  691.     tp->t_flag |= TF_CLOSE;
  692.     return 0;
  693. }
  694.  
  695.  
  696. /*    tm_exit()
  697. *
  698. *    Last message from a task.  This is the nice way of disconnecting.
  699. *
  700. *    TM_EXIT
  701. *    call { }
  702. *    ret { }
  703. */
  704.  
  705. int
  706. tm_exit(tp, mp)
  707.     struct task *tp;
  708.     struct pmsg *mp;
  709. {
  710.     mp = replymessage(mp);
  711.     tp->t_flag |= TF_CLOSE;
  712.     sendmessage(mp);
  713.     if (!(tp->t_flag & TF_FORKD))
  714.         task_cleanup(tp);
  715.     return 0;
  716. }
  717.  
  718.  
  719. /*    tm_pstat()
  720. *
  721. *    Task wants status of another task.
  722. *
  723. *    TM_PSTAT
  724. *    call {
  725. *        int tid
  726. *    }
  727. *    ret {
  728. *        int status
  729. *    }
  730. */
  731.  
  732. int
  733. tm_pstat(tp, mp)
  734.     struct task *tp;
  735.     struct pmsg *mp;
  736. {
  737.     int tid;
  738.     struct hostd *hp;
  739.     struct waitc *wp;
  740.  
  741.     /* unpack and sanity check tid */
  742.  
  743.     if (upkuint(mp, &tid)) {
  744.         pvmlogerror("tm_pstat() bad msg format\n");
  745.         return 0;
  746.     }
  747.     if (!TIDISTASK(tid)) {
  748.         pvmlogprintf("tm_pstat() bad tid %x\n", tid);
  749.         return 0;
  750.     }
  751.  
  752.     /* nack if no such host */
  753.  
  754.     if (!(hp = tidtohost(hosts, tid))) {
  755.         mp = replymessage(mp);
  756.         pkint(mp, PvmNoTask);
  757.         sendmessage(mp);
  758.         return 0;
  759.     }
  760.  
  761.     /* else make a wait context and send query */
  762.  
  763.     wp = wait_new(WT_PSTAT);
  764.     wp->wa_tid = tp->t_tid;
  765.     wp->wa_on = hp->hd_hostpart;
  766.     wp->wa_mesg = replymessage(mp);
  767.  
  768.     mp = mesg_new(0);
  769.     mp->m_dst = hp->hd_hostpart | TIDPVMD;
  770.     mp->m_tag = DM_PSTAT;
  771.     mp->m_wid = wp->wa_wid;
  772.     pkint(mp, tid);
  773.     sendmessage(mp);
  774.     return 0;
  775. }
  776.  
  777.  
  778. /*    tm_addhost()
  779. *
  780. *    Task requesting to add hosts to virtual machine.  Exit point is
  781. *    here or dm_addack().
  782. *
  783. *    TM_ADDHOST
  784. *    call {
  785. *        int nhosts
  786. *        string names[nhosts]
  787. *    }
  788. *    ret {
  789. *        int nhosts            // or error code
  790. *        int narches            // if nhosts >= 0
  791. *        {
  792. *            int tid            // or error code
  793. *            string name
  794. *            string arch
  795. *            int speed
  796. *            int dsig
  797. *        } [nhosts]
  798. *    }
  799. */
  800.  
  801. int
  802. tm_addhost(tp, mp)
  803.     struct task *tp;
  804.     struct pmsg *mp;
  805. {
  806.     int count;
  807.     char *buf;
  808.     struct waitc *wp;
  809.  
  810.     /* sanity check the message */
  811.  
  812.     if (upkint(mp, &count))
  813.         goto bad;
  814.     if (count < 1 || count > (tidhmask >> (ffs(tidhmask) - 1)))
  815.         goto bad;
  816.     while (count-- > 0) {
  817.         if (upkstralloc(mp, &buf))
  818.             goto bad;
  819.         else
  820.             PVM_FREE(buf);
  821.     }
  822.  
  823.     /* make a wait channel for the task */
  824.  
  825.     wp = wait_new(WT_ADDHOST);
  826.     wp->wa_tid = tp->t_tid;
  827.     wp->wa_on = hosts->ht_hosts[hosts->ht_master]->hd_hostpart;
  828.     wp->wa_mesg = replymessage(mp);
  829.  
  830.     /* forward message to master pvmd */
  831.  
  832.     mp->m_ref++;
  833.     mp->m_src = pvmmytid;
  834.     mp->m_dst = hosts->ht_hosts[hosts->ht_master]->hd_hostpart | TIDPVMD;
  835.     mp->m_tag = DM_ADD;
  836.     mp->m_wid = wp->wa_wid;
  837.     sendmessage(mp);
  838.     return 0;
  839.  
  840. bad:
  841.     pvmlogprintf("tm_addhost() from t%x bad msg format\n", mp->m_src);
  842.     return 0;
  843. }
  844.  
  845.  
  846. int
  847. free_wait_spawn(wxp)
  848.     struct waitc_spawn *wxp;
  849. {
  850.     int i;
  851.  
  852.     if (wxp->w_file)
  853.         PVM_FREE(wxp->w_file);
  854.     if (wxp->w_argv) {
  855.         for (i = 0; i < wxp->w_argc; i++)
  856.             if (wxp->w_argv[i])
  857.                 PVM_FREE(wxp->w_argv[i]);
  858.         PVM_FREE(wxp->w_argv);
  859.     }
  860.     if (wxp->w_env) {
  861.         for (i = 0; i < wxp->w_nenv; i++)
  862.             if (wxp->w_env[i])
  863.                 PVM_FREE(wxp->w_env[i]);
  864.         PVM_FREE(wxp->w_env);
  865.     }
  866.     if (wxp->w_ht)
  867.         ht_free(wxp->w_ht);
  868.     if (wxp->w_vec)
  869.         PVM_FREE(wxp->w_vec);
  870.     PVM_FREE(wxp);
  871.     return 0;
  872. }
  873.  
  874.  
  875. /*    tm_spawn()
  876. *
  877. *    Task requesting to spawn other tasks.  Exit point for this
  878. *    request is here or dm_execack().
  879. *
  880. *    TM_SPAWN
  881. *    call {
  882. *        string file
  883. *        int flags
  884. *        string where
  885. *        int count
  886. *        int nargs
  887. *        string argv[nargs]
  888. *        int outtid
  889. *        int outctx
  890. *        int outtag
  891. *        int trctid
  892. *        int trcctx
  893. *        int trctag
  894. *        int nenv
  895. *        string env[nenv]
  896. *    }
  897. *    ret {
  898. *        int ntids  // or nack
  899. *        int tids[acknack]
  900. *    }
  901. */
  902.  
  903. int
  904. tm_spawn(tp, mp)
  905.     struct task *tp;
  906.     struct pmsg *mp;
  907. {
  908.     char *where = 0;                /* location from req */
  909.     struct waitc *wp;                /* 'seed' waitc */
  910.     struct waitc_spawn *wxp = 0;    /* new task parameters */
  911.     struct htab *htp;                /* set of usable hosts */
  912.     struct hostd *hp;
  913.     int hh;
  914.     int i;
  915.  
  916.     /*
  917.     * unpack spawn command from task
  918.     */
  919.  
  920.     wxp = TALLOC(1, struct waitc_spawn, "waix");
  921.     BZERO((char*)wxp, sizeof(struct waitc_spawn));
  922.  
  923.     if (upkstralloc(mp, &wxp->w_file)
  924.     || upkint(mp, &wxp->w_flags)
  925.     || upkstralloc(mp, &where)
  926.     || upkint(mp, &wxp->w_veclen)
  927.     || upkint(mp, &wxp->w_argc))
  928.         goto bad;
  929.  
  930.     if (wxp->w_veclen < 1)
  931.         goto bad;
  932.  
  933.     wxp->w_argv = TALLOC(wxp->w_argc + 1, char*, "argv");
  934.     BZERO((char*)wxp->w_argv, (wxp->w_argc + 1) * sizeof(char*));
  935.     for (i = 0; i < wxp->w_argc; i++)
  936.         if (upkstralloc(mp, &wxp->w_argv[i]))
  937.             goto bad;
  938.  
  939.     if (upkuint(mp, &wxp->w_outtid)
  940.     || upkuint(mp, &wxp->w_outctx)
  941.     || upkuint(mp, &wxp->w_outtag)
  942.     || upkuint(mp, &wxp->w_trctid)
  943.     || upkuint(mp, &wxp->w_trcctx)
  944.     || upkuint(mp, &wxp->w_trctag))
  945.         goto bad;
  946.  
  947.     if (upkuint(mp, &wxp->w_nenv))
  948.         goto bad;
  949.     wxp->w_env = TALLOC((wxp->w_nenv + 1), char*, "env");
  950.     BZERO((char*)wxp->w_env, (wxp->w_nenv + 1) * sizeof(char*));
  951.     for (i = 0; i < wxp->w_nenv; i++)
  952.         if (upkstralloc(mp, &wxp->w_env[i]))
  953.             goto bad;
  954.  
  955.     /*
  956.     * make host set containing hosts (matching where option)
  957.     */
  958.  
  959.     if ((wxp->w_flags & (PvmTaskHost|PvmTaskArch)) && !where)
  960.         goto bad;
  961.  
  962.     htp = ht_new(1);
  963.  
  964.     if (wxp->w_flags & PvmTaskHost) {            /* given host */
  965.         if (hp = nametohost(hosts, where))
  966.             ht_insert(htp, hp);
  967.  
  968.     } else {
  969.         if (wxp->w_flags & PvmTaskArch) {        /* given arch */
  970.             for (hh = hosts->ht_last; hh > 0; hh--)
  971.                 if ((hp = hosts->ht_hosts[hh])
  972.                 && !strcmp(where, hp->hd_arch))
  973.                     ht_insert(htp, hp);
  974.  
  975.         } else {                        /* anywhere */
  976.             ht_merge(htp, hosts);
  977.         }
  978.     }
  979.  
  980.     if (wxp->w_flags & PvmHostCompl) {
  981.         for (hh = hosts->ht_last; hh > 0; hh--) {
  982.             if (hh <= htp->ht_last && (hp = htp->ht_hosts[hh]))
  983.                 ht_delete(htp, hp);
  984.             else
  985.                 if (hp = hosts->ht_hosts[hh])
  986.                     ht_insert(htp, hp);
  987.         }
  988.     }
  989.  
  990.     if (pvmdebmask & PDMTASK) {
  991.         pvmlogerror("tm_spawn() host set:\n");
  992.         ht_dump(htp);
  993.     }
  994.  
  995.     if ( !(wxp->w_flags & PvmNoSpawnParent) ) {
  996.         wxp->w_ptid = tp->t_tid;
  997.     }
  998.     else
  999.         wxp->w_ptid = PvmParentNotSet;    /* indicate that task unset parent */
  1000.  
  1001.     /*
  1002.     * assign each task to a host
  1003.     */
  1004.  
  1005.     wxp->w_ht = htp;
  1006.     wxp->w_vec = TALLOC(wxp->w_veclen, int, "vec");
  1007.     BZERO((char*)wxp->w_vec, wxp->w_veclen * sizeof(int));
  1008.     wxp->w_togo = wxp->w_veclen;
  1009.  
  1010.     wp = wait_new(WT_SPAWN);
  1011.     wp->wa_tid = tp->t_tid;
  1012.     wp->wa_spec = (void*)wxp;
  1013.     wxp = 0;
  1014.     wp->wa_mesg = replymessage(mp);
  1015.  
  1016.     assign_tasks(wp);
  1017.  
  1018.     /* if already done, reply to task */
  1019.  
  1020.     if (wp->wa_peer == wp) {
  1021.         assign_tasks(wp);
  1022.     }
  1023.  
  1024.     wait_delete(wp);
  1025.     goto cleanup;
  1026.  
  1027. bad:
  1028.     pvmlogprintf("tm_spawn() from t%x bad msg format\n", mp->m_src);
  1029.  
  1030. cleanup:
  1031.     if (where)
  1032.         PVM_FREE(where);
  1033.     if (wxp)
  1034.         free_wait_spawn(wxp);
  1035.     return 0;
  1036. }
  1037.  
  1038.  
  1039. /*    assign_tasks()
  1040. *
  1041. *    This is only called when no replies are pending (at the beginning
  1042. *    of the operation or when all pvmds have checked back in).
  1043. */
  1044.  
  1045. assign_tasks(wp)
  1046.     struct waitc *wp;        /* (any) waitc in peer group for this op */
  1047. {
  1048.     static int lasthh = -1;            /* for assigning hosts */
  1049.  
  1050.     struct waitc_spawn *wxp = (struct waitc_spawn*)wp->wa_spec;
  1051.     struct htab *htp;                /* set of hosts to use */
  1052.     int *vec;                        /* result/status vector */
  1053.     int veclen;                        /* length of vector */
  1054.     int count = 0;                    /* num of tasks to be assigned */
  1055.     int nh;                            /* num of hosts to assign tasks */
  1056.     int a = 0;                        /* accum for finding hosts */
  1057.     int na = 0;                        /* num tasks assigned to a host */
  1058.     struct waitc *wp2;
  1059.     struct hostd *hp;
  1060.     struct pmsg *mp;
  1061.     int t;
  1062.     int i;
  1063.     int tid;
  1064.     struct timeval now;
  1065.  
  1066.     if (!wxp)
  1067.         return 0;
  1068.  
  1069.     htp = wxp->w_ht;
  1070.     vec = wxp->w_vec;
  1071.     veclen = wxp->w_veclen;
  1072.  
  1073.     /*
  1074.     * if no hosts left, fill unassigned entries with PvmNoHost
  1075.     */
  1076.  
  1077.     if (!htp->ht_cnt)
  1078.         for (t = veclen; t-- > 0; )
  1079.             if (!vec[t])
  1080.                 vec[t] = PvmNoHost;
  1081.  
  1082.     /*
  1083.     * count tasks to be assigned, if none left reply to task
  1084.     */
  1085.  
  1086.     for (t = veclen; t-- > 0; )
  1087.         if (!vec[t])
  1088.             count++;
  1089.  
  1090.     if (!count) {
  1091.         pkint(wp->wa_mesg, wxp->w_veclen);
  1092.         for (t = 0; t < wxp->w_veclen; t++) {
  1093.             tid = wxp->w_vec[t];
  1094.             pkint(wp->wa_mesg, tid);
  1095.             if (TIDISTASK(tid) && wxp->w_trctid > 0) {
  1096.                 tev_send_spntask(
  1097.                     wxp->w_trctid, wxp->w_trcctx, wxp->w_trctag,
  1098.                     tid, wxp->w_ptid );
  1099.             }
  1100.             if (TIDISTASK(tid) && wxp->w_outtid > 0) {
  1101.                 mp = mesg_new(0);
  1102.                 mp->m_dst = wxp->w_outtid;
  1103.                 mp->m_ctx = wxp->w_outctx;
  1104.                 mp->m_tag = wxp->w_outtag;
  1105.                 pkint(mp, tid);
  1106.                 pkint(mp, -1);
  1107.                 pkint(mp, wxp->w_ptid);
  1108.                 sendmessage(mp);
  1109.             }
  1110.         }
  1111.         sendmessage(wp->wa_mesg);
  1112. wp->wa_mesg = 0;
  1113.  
  1114.         free_wait_spawn(wxp);
  1115.         wp->wa_spec = 0;
  1116.         return 0;
  1117.     }
  1118.  
  1119.     /*
  1120.     * assign tasks to hosts
  1121.     */
  1122.  
  1123.     nh = min(htp->ht_cnt, count);
  1124.  
  1125.     /* find first host to assign */
  1126.  
  1127.     if (lasthh == -1)
  1128.         lasthh = hosts->ht_local + 1;
  1129.     if (lasthh > htp->ht_last)
  1130.         lasthh = 0;
  1131.     while (!htp->ht_hosts[lasthh])
  1132.         if (++lasthh > htp->ht_last)
  1133.             lasthh = 1;
  1134.     hp = htp->ht_hosts[lasthh];
  1135.  
  1136.     for (t = 0; t < veclen && vec[t]; t++);
  1137.  
  1138.     while (t < veclen) {
  1139. /*
  1140.         pvmlogprintf("assign_tasks() %s <- %d\n", hp->hd_name, t);
  1141. */
  1142.  
  1143.         vec[t] = hp->hd_hostpart;
  1144.         na++;
  1145.  
  1146.     /* when enough tasks for this host, move to next */
  1147.  
  1148.         if ((a += nh) >= count) {
  1149.             a -= count;
  1150.  
  1151.             wp2 = wait_new(WT_SPAWN);
  1152.             wp2->wa_tid = wp->wa_tid;
  1153.             wp2->wa_on = hp->hd_hostpart;
  1154.             wp2->wa_spec = wp->wa_spec;
  1155.             wp->wa_mesg->m_ref++;
  1156.             wp2->wa_mesg = wp->wa_mesg;
  1157.             LISTPUTBEFORE(wp, wp2, wa_peer, wa_rpeer);
  1158.  
  1159.             mp = mesg_new(0);
  1160.             pkint(mp, wxp->w_ptid);
  1161.             pkstr(mp, wxp->w_file);
  1162.             pkint(mp, wxp->w_flags);
  1163.             pkint(mp, na);
  1164.             pkint(mp, wxp->w_argc);
  1165.             for (i = 0; i < wxp->w_argc; i++)
  1166.                 pkstr(mp, wxp->w_argv[i]);
  1167.             pkint(mp, wxp->w_outtid);
  1168.             pkint(mp, wxp->w_outctx);
  1169.             pkint(mp, wxp->w_outtag);
  1170.             pkint(mp, wxp->w_trctid);
  1171.             pkint(mp, wxp->w_trcctx);
  1172.             pkint(mp, wxp->w_trctag);
  1173.             pkint(mp, wxp->w_nenv);
  1174.             for (i = 0; i < wxp->w_nenv; i++)
  1175.                 pkstr(mp, wxp->w_env[i]);
  1176.             pkint(mp, (t+1)-na);    /* start proc location 0..count-1 */
  1177.             pkint(mp, count);        /* how many are there in total */
  1178.             mp->m_dst = hp->hd_hostpart | TIDPVMD;
  1179.             mp->m_tag = DM_EXEC;
  1180.             mp->m_wid = wp2->wa_wid;
  1181.  
  1182.             do {
  1183.                 if (++lasthh > htp->ht_last)
  1184.                     lasthh = 1;
  1185.             } while (!htp->ht_hosts[lasthh]);
  1186.  
  1187.             sendmessage(mp);
  1188.  
  1189.             hp = htp->ht_hosts[lasthh];
  1190.             na = 0;
  1191.         }
  1192.         for (t++ ; t < veclen && vec[t]; t++);
  1193.     }
  1194.     return 0;
  1195. }
  1196.  
  1197.  
  1198. /*    tm_sendsig()
  1199. *
  1200. *    Task sending a signal to another task.
  1201. *
  1202. *    TM_SENDSIG
  1203. *    call {
  1204. *        int tid
  1205. *        int signum
  1206. *    }
  1207. *    ret { }
  1208. */
  1209.  
  1210. int
  1211. tm_sendsig(tp, mp)
  1212.     struct task *tp;
  1213.     struct pmsg *mp;
  1214. {
  1215.     int tid;
  1216.     struct pmsg *mp2;
  1217.  
  1218.     if (upkuint(mp, &tid)) {
  1219.         pvmlogerror("tm_sendsig() bad msg format\n");
  1220.         return 0;
  1221.     }
  1222.     if (!TIDISTASK(tid)) {
  1223.         pvmlogprintf("tm_sendsig() bad tid %x\n", tid);
  1224.         return 0;
  1225.     }
  1226.  
  1227.     mp2 = replymessage(mp);
  1228.     sendmessage(mp2);
  1229.  
  1230.     mp->m_ref++;
  1231.     mp->m_src = pvmmytid;
  1232.     mp->m_dst = (tid & TIDHOST) | TIDPVMD;
  1233.     mp->m_tag = DM_SENDSIG;
  1234.     mp->m_wid = 0;
  1235.     sendmessage(mp);
  1236.     return 0;
  1237. }
  1238.  
  1239.  
  1240. /*    tm_config()
  1241. *
  1242. *    Task wants machine configuration.
  1243. *
  1244. *    TM_CONFIG
  1245. *    call { }
  1246. *    ret {
  1247. *        int nhosts
  1248. *        int narches
  1249. *        {
  1250. *            int tid
  1251. *            string name
  1252. *            string arch
  1253. *            int speed
  1254. *            int dsig
  1255. *        } [nhosts]
  1256. *    }
  1257. */
  1258.  
  1259. int
  1260. tm_config(tp, mp)
  1261.     struct task *tp;
  1262.     struct pmsg *mp;
  1263. {
  1264.     int hh;
  1265.     struct hostd *hp;
  1266.  
  1267.     mp = replymessage(mp);
  1268.     pkint(mp, hosts->ht_cnt);
  1269.     pkint(mp, hosts->ht_narch);
  1270.     for (hh = 1; hh <= hosts->ht_last; hh++) {
  1271.         if (hp = hosts->ht_hosts[hh]) {
  1272.             pkint(mp, hp->hd_hostpart);
  1273.             pkstr(mp, hp->hd_name);
  1274.             pkstr(mp, hp->hd_arch ? hp->hd_arch : "");
  1275.             pkint(mp, hp->hd_speed);
  1276.             pkint(mp, hp->hd_dsig);
  1277.         }
  1278.     }
  1279.     sendmessage(mp);
  1280.     return 0;
  1281. }
  1282.  
  1283.  
  1284. /*    tm_halt()
  1285. *
  1286. *    Command from task to stop master pvmd.
  1287. *
  1288. *    TM_HALT
  1289. *    call { }
  1290. *    ret { }
  1291. */
  1292.  
  1293. int
  1294. tm_halt(tp, mp)
  1295.     struct task *tp;
  1296.     struct pmsg *mp;
  1297. {
  1298.     mp = mesg_new(0);
  1299.     mp->m_tag = DM_HALT;
  1300.     mp->m_dst = hosts->ht_hosts[hosts->ht_master]->hd_hostpart | TIDPVMD;
  1301.     sendmessage(mp);
  1302.     return 0;
  1303. }
  1304.  
  1305.  
  1306. /*    tm_task()
  1307. *
  1308. *    Task wants a list of tasks.
  1309. *    If where is a host or task tid, give a list of matching tasks.
  1310. *    If where is zero, give all running tasks.
  1311. *
  1312. *    TM_TASK
  1313. *    call {
  1314. *        int where
  1315. *    }
  1316. *    ret {
  1317. *        int errcode
  1318. *        {
  1319. *            int tid
  1320. *            int ptid
  1321. *            int hostpart
  1322. *            int flag
  1323. *            string a_out
  1324. *            int pid
  1325. *        } [count]    // implied
  1326. *    }
  1327. */
  1328.  
  1329. int
  1330. tm_task(tp, mp)
  1331.     struct task *tp;
  1332.     struct pmsg *mp;
  1333. {
  1334.     int where;
  1335.     struct pmsg *mp2;
  1336.     struct waitc *wp;
  1337.     struct waitc *wp2 = 0;    /* master waitc of peer group */
  1338.     int hh;
  1339.     struct hostd *hp;
  1340.  
  1341.     if (upkuint(mp, &where)) {
  1342.         pvmlogerror("tm_task() bad msg format\n");
  1343.         return 0;
  1344.     }
  1345.  
  1346.     mp = replymessage(mp);
  1347.     mp->m_dst = tp->t_tid;
  1348.     mp->m_tag = TM_TASK;
  1349.  
  1350.     if (where) {        /* specific host or task requested */
  1351.         if (!(hp = tidtohost(hosts, where))) {
  1352.             pkint(mp, PvmNoHost);
  1353.             sendmessage(mp);
  1354.             return 0;
  1355.         }
  1356.         pkint(mp, 0);
  1357.         wp = wait_new(WT_TASK);
  1358.         wp->wa_mesg = mp;
  1359.         wp->wa_tid = tp->t_tid;
  1360.         wp->wa_on = hp->hd_hostpart;
  1361.  
  1362.         mp = mesg_new(0);
  1363.         mp->m_tag = DM_TASK;
  1364.         mp->m_dst = hp->hd_hostpart | TIDPVMD;
  1365.         mp->m_wid = wp->wa_wid;
  1366.         pkint(mp, where);
  1367.         sendmessage(mp);
  1368.  
  1369.     } else {            /* all tasks requested */
  1370.         pkint(mp, 0);
  1371.  
  1372.         wp2 = wait_new(WT_TASK);
  1373.         mp->m_ref++;
  1374.         wp2->wa_mesg = mp;
  1375.         wp2->wa_tid = tp->t_tid;
  1376.  
  1377.         mp2 = mesg_new(0);
  1378.         mp2->m_tag = DM_TASK;
  1379.         pkint(mp2, 0);
  1380.  
  1381.         for (hh = hosts->ht_last; hh > 0; hh--) {
  1382.             if (!hosts->ht_hosts[hh])
  1383.                 continue;
  1384.  
  1385.             wp = wait_new(WT_TASK);
  1386.             mp->m_ref++;
  1387.             wp->wa_mesg = mp;
  1388.             wp->wa_tid = tp->t_tid;
  1389.             wp->wa_on = hosts->ht_hosts[hh]->hd_hostpart;
  1390.  
  1391.             LISTPUTBEFORE(wp2, wp, wa_peer, wa_rpeer);
  1392.  
  1393.             mp2->m_dst = hosts->ht_hosts[hh]->hd_hostpart | TIDPVMD;
  1394.             mp2->m_wid = wp->wa_wid;
  1395.             mp2->m_ref++;
  1396.             sendmessage(mp2);
  1397.         }
  1398.         pmsg_unref(mp2);
  1399.         pmsg_unref(mp);
  1400.  
  1401.         /* send message if all waiters are in */
  1402.  
  1403.         if (wp2->wa_peer == wp2) {
  1404.             mp->m_ref++;
  1405.             sendmessage(mp);
  1406.         }
  1407.         wait_delete(wp2);
  1408.     }
  1409.     return 0;
  1410. }
  1411.  
  1412.  
  1413. /*    tm_tickle()
  1414. *
  1415. *    Task wants to poke at pvmd.
  1416. *
  1417. *    TM_TICKLE
  1418. *    call {
  1419. *        int nargs
  1420. *        int args[nargs]
  1421. *    }
  1422. *    ret {
  1423. *        int nresult
  1424. *        int results[nresult]
  1425. *    }
  1426. */
  1427.  
  1428. int
  1429. tm_tickle(tp, mp)
  1430.     struct task *tp;
  1431.     struct pmsg *mp;
  1432. {
  1433.     int nar;
  1434.     int arg[10];
  1435.     int i;
  1436.     char *p;
  1437.     struct hostd *hp;
  1438.  
  1439.     upkint(mp, &nar);
  1440.     if (nar < 1 || nar > 10) {
  1441.         pvmlogprintf("tm_tickle() bad msg format\n");
  1442.         return 0;
  1443.     }
  1444.     for (i = 0; i < nar; i++)
  1445.         upkint(mp, &arg[i]);
  1446.     while (i < sizeof(arg)/sizeof(arg[0]))
  1447.         arg[i++] = 0;
  1448.  
  1449.     pvmlogprintf("tm_tickle() #");
  1450.     for (i = 0; i < nar; i++)
  1451.         pvmlogprintf(" %d", arg[i]);
  1452.     pvmlogprintf("\n");
  1453.  
  1454.     mp = replymessage(mp);
  1455.  
  1456.     switch (arg[0]) {
  1457.  
  1458.     case 0:
  1459.         i_dump(1);
  1460.         pkint(mp, 0);
  1461.         break;
  1462.  
  1463.     case 1:
  1464.         ht_dump(hosts);
  1465.         pkint(mp, 0);
  1466.         break;
  1467.  
  1468.     case 2:
  1469.         task_dump();
  1470.         pkint(mp, 0);
  1471.         break;
  1472.  
  1473.     case 3:
  1474.         wait_dumpall();
  1475.         pkint(mp, 0);
  1476.         break;
  1477.  
  1478.     case 4:
  1479.         mb_dumpall();
  1480.         pkint(mp, 0);
  1481.         break;
  1482.  
  1483.     case 5:
  1484.         pkint(mp, 1);
  1485.         pkint(mp, pvmdebmask);
  1486.         break;
  1487.  
  1488.     case 6:
  1489.         pvmdebmask = arg[1];
  1490.         pvmlogprintf("tm_tickle() debug mask is %x (%s)\n",
  1491.                 pvmdebmask, debug_flags(pvmdebmask));
  1492.         pkint(mp, 0);
  1493.         break;
  1494.  
  1495.     case 7:
  1496.         if (arg[1] > 0 && arg[1] < 50) {
  1497.             nopax = arg[1];
  1498.             pvmlogprintf("tm_tickle() nopax is %d\n", nopax);
  1499.         } else
  1500.             pvmlogprintf("tm_tickle() bogus nopax %d\n", arg[1]);
  1501.         pkint(mp, 0);
  1502.         break;
  1503.  
  1504.     case 8:
  1505.         pkint(mp, 1);
  1506.         if ((hp = tidtohost(hosts, arg[1]))
  1507.         && hp != hosts->ht_hosts[hosts->ht_local]) {
  1508.             pvmlogprintf("tm_tickle() failing %s\n", hp->hd_name);
  1509.             hostfailentry(hp);
  1510.             ht_delete(hosts, hp);
  1511.             if (newhosts)
  1512.                 ht_delete(newhosts, hp);
  1513.             pkint(mp, 1);
  1514.         } else {
  1515.             if (hp)
  1516.                 pvmlogprintf("tm_tickle() can't fail %s\n", hp->hd_name);
  1517.             else
  1518.                 pvmlogprintf("tm_tickle() no such host %x\n", arg[1]);
  1519.             pkint(mp, 0);
  1520.         }
  1521.         break;
  1522.  
  1523.     case 9:
  1524. #ifdef    STATISTICS
  1525.         dump_statistics();
  1526.         if (arg[1])
  1527.             reset_statistics();
  1528. #else
  1529.         pvmlogerror("tm_tickle() statistics not compiled in\n");
  1530. #endif
  1531.         pkint(mp, 0);
  1532.         break;
  1533.  
  1534.     case 100:
  1535. #ifdef SHMEM
  1536.         peer_dump();
  1537.         pidtid_dump();
  1538. #else
  1539.         pvmlogerror("tm_tickle() not using shared memory\n");
  1540. #endif
  1541.         pkint(mp, 0);
  1542.         break;
  1543.  
  1544.     case 20:
  1545.         {
  1546.             struct pmsg *mp2;
  1547.             int i, j;
  1548.  
  1549.             for (j = 0; j < arg[1]; j++) {
  1550.                 mp2 = mesg_new(0);
  1551.                 for (i = 0; i < 1000; i++)
  1552.                     pkint(mp2, i);
  1553.                 mp2->m_dst = arg[2];
  1554.                 mp2->m_tag = DM_NULL;
  1555.                 sendmessage(mp2);
  1556.             }
  1557.             pkint(mp, 0);
  1558.         }
  1559.         break;
  1560.  
  1561.     default:
  1562.         pvmlogprintf("tm_tickle() don't know #%d\n", arg[0]);
  1563.         pkint(mp, 0);
  1564.         break;
  1565.     }
  1566.  
  1567.     sendmessage(mp);
  1568.     return 0;
  1569. }
  1570.  
  1571.  
  1572. /*    tm_delhost()
  1573. *
  1574. *    Task requesting to add hosts to virtual machine.  Exit point is
  1575. *    here or dm_delhostack().
  1576. *
  1577. *    TM_DELHOST
  1578. *    call {
  1579. *        int nhosts
  1580. *        string names[nhosts]
  1581. *    }
  1582. *    ret {
  1583. *        int nhosts            // or negative for error
  1584. *        int status[nhosts]    // status of each host
  1585. *    }
  1586. */
  1587.  
  1588. int
  1589. tm_delhost(tp, mp)
  1590.     struct task *tp;
  1591.     struct pmsg *mp;
  1592. {
  1593.     int count;
  1594.     char *buf;
  1595.     struct waitc *wp;
  1596.  
  1597.     /* sanity check the message */
  1598.  
  1599.     if (upkint(mp, &count))
  1600.         goto bad;
  1601.     if (count < 1 || count > (tidhmask >> (ffs(tidhmask) - 1)))
  1602.         goto bad;
  1603.     while (count-- > 0)
  1604.         if (upkstralloc(mp, &buf))
  1605.             goto bad;
  1606.         else
  1607.             PVM_FREE(buf);
  1608.  
  1609.     /* make a wait channel for the task */
  1610.  
  1611.     wp = wait_new(WT_DELHOST);
  1612.     wp->wa_tid = tp->t_tid;
  1613.     wp->wa_on = hosts->ht_hosts[hosts->ht_master]->hd_hostpart;
  1614.     wp->wa_mesg = replymessage(mp);
  1615.  
  1616.     /* forward message to master pvmd */
  1617.  
  1618.     mp->m_ref++;
  1619.     mp->m_src = pvmmytid;
  1620.     mp->m_dst = hosts->ht_hosts[hosts->ht_master]->hd_hostpart | TIDPVMD;
  1621.     mp->m_tag = DM_DELHOST;
  1622.     mp->m_wid = wp->wa_wid;
  1623.     sendmessage(mp);
  1624.     return 0;
  1625.  
  1626. bad:
  1627.     pvmlogprintf("tm_delhost() from t%x bad msg format\n", mp->m_src);
  1628.     return 0;
  1629. }
  1630.  
  1631.  
  1632. /*    tm_mca()
  1633. *
  1634. *    Task announces multicast address list for subsequent message.
  1635. *
  1636. *    TM_MCA
  1637. *    call {
  1638. *        int count            // number of addresses
  1639. *        int tids[count]        // addresses
  1640. *    }
  1641. *    // No Return
  1642. */
  1643.  
  1644. int
  1645. tm_mca(tp, mp)
  1646.     struct task *tp;
  1647.     struct pmsg *mp;
  1648. {
  1649.     struct mca *mcap;            /* mca descriptor */
  1650.     int ndst;                    /* num of dst tids */
  1651.     int *dsts;                    /* dst tids */
  1652.     int tid;
  1653.     int i, j;
  1654.  
  1655.     /*
  1656.     * unpack list of dst tids from message (expect it to be sorted).
  1657.     * discard tids to nonexistent foreign hosts.
  1658.     */
  1659.  
  1660.     mcap = mca_new();
  1661.     mcap->mc_tid = TIDGID | tp->t_tid;
  1662.     upkint(mp, &ndst);
  1663.     dsts = TALLOC(ndst, int, "dsts");
  1664.     for (i = 0; i < ndst; ) {
  1665.         upkuint(mp, &tid);
  1666.         if ((tid & tidhmask) == myhostpart || tidtohost(hosts, tid))
  1667.             dsts[i++] = tid;
  1668.     }
  1669.     ndst = i;
  1670.  
  1671.     if (ndst < 1)
  1672.         goto noguys;
  1673.  
  1674.     /*
  1675.     * send DM_MCA messages containing tids to destination hosts
  1676.     * make list of destination hosts for us
  1677.     */
  1678.  
  1679.     mcap->mc_dsts = TALLOC(ndst, int, "mcal");    /* XXX cheat, too much space */
  1680.     mcap->mc_ndst = 0;
  1681.  
  1682.     for (j = 0; j < ndst; ) {
  1683.         i = j;
  1684.         tid = dsts[i] & tidhmask;
  1685.         while (++j < ndst && tid == (dsts[j] & tidhmask)) ;
  1686.         mp = mesg_new(0);
  1687.         mp->m_dst = (tid |= TIDPVMD);
  1688.         mp->m_tag = DM_MCA;
  1689.         pkint(mp, mcap->mc_tid);
  1690.         pkint(mp, j - i);
  1691.         while (i < j)
  1692.             pkint(mp, dsts[i++]);
  1693.         sendmessage(mp);
  1694.         mcap->mc_dsts[mcap->mc_ndst++] = tid;
  1695.     }
  1696.  
  1697. noguys:
  1698.     PVM_FREE(dsts);
  1699.  
  1700.     /*
  1701.     * tag task descriptor with mca desc and send mca back to task
  1702.     */
  1703.  
  1704.     tp->t_mca = mcap;
  1705.  
  1706.     if (pvmdebmask & PDMMESSAGE) {
  1707.         pvmlogprintf("tm_mca() made mca %x for t%x\n",
  1708.                 mcap->mc_tid, tp->t_tid);
  1709.     }
  1710.     return 0;
  1711. }
  1712.  
  1713.  
  1714. /*    tm_notify()
  1715. *
  1716. *    Task wants to be notified when an event happens.
  1717. *
  1718. *    TM_NOTIFY
  1719. *    call {
  1720. *        int what            // event type and flags
  1721. *        int ctx                // message context to use in reply
  1722. *        int tag                // message tag to use in reply
  1723. *        int count            // number of addresses
  1724. *        int tids[count]        // addresses
  1725. *    }
  1726. *    // No Return
  1727. */
  1728.  
  1729. int
  1730. tm_notify(tp, mp)
  1731.     struct task *tp;
  1732.     struct pmsg *mp;
  1733. {
  1734.     int what, flags, ctx, tag, count, tid;
  1735.     struct hostd *hp;
  1736.     struct pmsg *mp2;
  1737.     struct waitc *wp;
  1738.     int i;
  1739.  
  1740.     if (upkint(mp, &what)
  1741.     || upkint(mp, &ctx)
  1742.     || upkint(mp, &tag)
  1743.     || upkint(mp, &count)) {
  1744.         pvmlogerror("tm_notify() bad msg format\n");
  1745.         return 0;
  1746.     }
  1747.  
  1748.     flags = what;
  1749.     what &= 0xff;
  1750.     switch (what) {
  1751.  
  1752.     /*
  1753.     * TaskExit: make a wait context that hangs out until the task is
  1754.     * cleaned up.
  1755.     */
  1756.  
  1757.     case PvmTaskExit:
  1758.         for (i = 0; i < count; i++) {
  1759.             if (upkuint(mp, &tid)) {
  1760.                 pvmlogerror("tm_notify() bad msg format\n");
  1761.                 return 0;
  1762.             }
  1763.  
  1764.             if (flags & PvmNotifyCancel) {
  1765.                 FORLIST (wp, waitlist, wa_link)
  1766.                     if (wp->wa_kind == WT_TASKX
  1767.                     && wp->wa_on == tid
  1768.                     && wp->wa_tid == tp->t_tid
  1769.                     && wp->wa_mesg->m_ctx == ctx
  1770.                     && wp->wa_mesg->m_tag == tag)
  1771.                         break;
  1772.                 if (wp != waitlist) {
  1773.                     sendmessage(wp->wa_mesg);
  1774.                     wp->wa_mesg = 0;
  1775.                     if ((hp = tidtohost(hosts, tid))
  1776.                     && hp->hd_hostpart != myhostpart)
  1777.                         wp->wa_tid = 0;
  1778.                     else
  1779.                         wait_delete(wp);
  1780.                 }
  1781.  
  1782.             } else {
  1783.                 /* make reply message */
  1784.  
  1785.                 mp2 = mesg_new(0);
  1786.                 mp2->m_dst = tp->t_tid;
  1787.                 mp2->m_ctx = ctx;
  1788.                 mp2->m_tag = tag;
  1789.                 mp2->m_wid = mp->m_wid;
  1790.                 pkint(mp2, tid);
  1791.  
  1792.                 /* if task doesn't exist, reply immediately */
  1793.  
  1794.                 if (!(hp = tidtohost(hosts, tid))
  1795.                 || (hp->hd_hostpart == myhostpart && !task_find(tid)))
  1796.                     sendmessage(mp2);
  1797.  
  1798.                 else {
  1799.  
  1800.                     /* otherwise make a wc for it */
  1801.  
  1802.                     wp = wait_new(WT_TASKX);
  1803.                     wp->wa_on = tid;
  1804.                     wp->wa_tid = tp->t_tid;
  1805.                     wp->wa_dep = mp->m_wid;
  1806.                     wp->wa_mesg = mp2;
  1807.  
  1808.                     /* and if not on this host, pass on the request */
  1809.  
  1810.                     if (hp->hd_hostpart != myhostpart) {
  1811.                         mp2 = mesg_new(0);
  1812.                         pkint(mp2, what);
  1813.                         pkint(mp2, tid);
  1814.                         mp2->m_dst = hp->hd_hostpart | TIDPVMD;
  1815.                         mp2->m_tag = DM_NOTIFY;
  1816.                         mp2->m_wid = wp->wa_wid;
  1817.                         sendmessage(mp2);
  1818.                     }
  1819.                 }
  1820.             }
  1821.         }
  1822.         break;
  1823.  
  1824.     case PvmHostDelete:
  1825.         for (i = 0; i < count; i++) {
  1826.             if (upkuint(mp, &tid)) {
  1827.                 pvmlogerror("tm_notify() bad msg format\n");
  1828.                 return 0;
  1829.             }
  1830.             if (flags & PvmNotifyCancel) {
  1831.                 if (hp = tidtohost(hosts, tid)) {
  1832.                     FORLIST (wp, waitlist, wa_link)
  1833.                         if (wp->wa_kind == WT_HOSTF
  1834.                         && wp->wa_on == hp->hd_hostpart
  1835.                         && wp->wa_tid == tp->t_tid
  1836.                         && wp->wa_mesg->m_ctx == ctx
  1837.                         && wp->wa_mesg->m_tag == tag)
  1838.                             break;
  1839.                     if (wp != waitlist) {
  1840.                         sendmessage(wp->wa_mesg);
  1841.                         wp->wa_mesg = 0;
  1842.                         wait_delete(wp);
  1843.                     }
  1844.                 }
  1845.  
  1846.             } else {
  1847.                 mp2 = mesg_new(0);
  1848.                 mp2->m_dst = mp->m_src;
  1849.                 mp2->m_ctx = ctx;
  1850.                 mp2->m_tag = tag;
  1851.                 pkint(mp2, tid);
  1852.                 if (hp = tidtohost(hosts, tid)) {
  1853.                     wp = wait_new(WT_HOSTF);
  1854.                     wp->wa_tid = tp->t_tid;
  1855.                     wp->wa_on = hp->hd_hostpart;
  1856.                     wp->wa_mesg = mp2;
  1857.  
  1858.                 } else {
  1859.                     sendmessage(mp2);
  1860.                 }
  1861.             }
  1862.         }
  1863.         break;
  1864.  
  1865.     case PvmHostAdd:
  1866.  
  1867.         FORLIST (wp, waitlist, wa_link)
  1868.             if (wp->wa_kind == WT_HOSTA
  1869.             && wp->wa_tid == tp->t_tid
  1870.             && wp->wa_mesg->m_ctx == ctx
  1871.             && wp->wa_mesg->m_tag == tag)
  1872.                 break;
  1873.  
  1874.     /* if cancelling, delete possible existing waitc */
  1875.  
  1876.         if (count == 0 || (flags & PvmNotifyCancel)) {
  1877.             if (wp != waitlist)
  1878.                 wait_delete(wp);
  1879.  
  1880.     /* otherwise, update existing waitc or create new one */
  1881.         } else {
  1882.             if (wp == waitlist) {
  1883.                 wp = wait_new(WT_HOSTA);
  1884.                 wp->wa_tid = tp->t_tid;
  1885.                 wp->wa_on = tp->t_tid;
  1886.                 wp->wa_mesg = mesg_new(0);
  1887.                 wp->wa_mesg->m_dst = tp->t_tid;
  1888.                 wp->wa_mesg->m_ctx = ctx;
  1889.                 wp->wa_mesg->m_tag = tag;
  1890.             }
  1891.             wp->wa_count = count;
  1892.         }
  1893.         break;
  1894.  
  1895.     default:
  1896.         pvmlogprintf("tm_notify() unknown what=%d\n", what);
  1897.         break;
  1898.     }
  1899.     return 0;
  1900. }
  1901.  
  1902.  
  1903. /*    tm_mstat()
  1904. *
  1905. *    Task wants status of a host.
  1906. *
  1907. *    TM_MSTAT
  1908. *    call {
  1909. *        string hostname
  1910. *    }
  1911. *    ret {
  1912. *        int status
  1913. *    }
  1914. */
  1915.  
  1916. int
  1917. tm_mstat(tp, mp)
  1918.     struct task *tp;
  1919.     struct pmsg *mp;
  1920. {
  1921.     char *name;
  1922.     struct hostd *hp;
  1923.     struct waitc *wp;
  1924.  
  1925.     if (upkstralloc(mp, &name)) {
  1926.         pvmlogerror("tm_mstat() bad msg format\n");
  1927.         return 0;
  1928.     }
  1929.  
  1930.     hp = nametohost(hosts, name);
  1931.  
  1932.     PVM_FREE(name);
  1933.  
  1934.     if (!hp) {
  1935.         mp = replymessage(mp);
  1936.         pkint(mp, PvmNoHost);
  1937.         sendmessage(mp);
  1938.         return 0;
  1939.     }
  1940.  
  1941.     wp = wait_new(WT_MSTAT);
  1942.     wp->wa_tid = tp->t_tid;
  1943.     wp->wa_on = hp->hd_hostpart;
  1944.     wp->wa_mesg = replymessage(mp);
  1945.  
  1946.     mp = mesg_new(0);
  1947.     mp->m_dst = hp->hd_hostpart | TIDPVMD;
  1948.     mp->m_tag = DM_PSTAT;
  1949.     mp->m_wid = wp->wa_wid;
  1950.     pkint(mp, hp->hd_hostpart | TIDPVMD);
  1951.     sendmessage(mp);
  1952.     return 0;
  1953. }
  1954.  
  1955.  
  1956. /*    tm_db()
  1957. *
  1958. *    Task wants a database op.
  1959. *
  1960. *    TM_DB
  1961. *    call {
  1962. *        int opcode        // insert, delete, lookup
  1963. *        string name
  1964. *        int index
  1965. *        int data        // if 'insert'
  1966. *    }
  1967. *    ret {
  1968. *        int index        // and status
  1969. *        int data        // if 'lookup'
  1970. *    }
  1971. */
  1972.  
  1973. int
  1974. tm_db(tp, mp)
  1975.     struct task *tp;
  1976.     struct pmsg *mp;
  1977. {
  1978.     struct waitc *wp;
  1979.  
  1980.     wp = wait_new(WT_DB);
  1981.     wp->wa_tid = tp->t_tid;
  1982.     wp->wa_on = hosts->ht_hosts[hosts->ht_master]->hd_hostpart;
  1983.     wp->wa_mesg = replymessage(mp);
  1984.  
  1985.     mp->m_ref++;
  1986.     mp->m_src = pvmmytid;
  1987.     mp->m_dst = hosts->ht_hosts[hosts->ht_master]->hd_hostpart | TIDPVMD;
  1988.     mp->m_tag = DM_DB;
  1989.     mp->m_wid = wp->wa_wid;
  1990.     sendmessage(mp);
  1991.     return 0;
  1992. }
  1993.  
  1994.  
  1995. /*    tm_sched()
  1996. *
  1997. *    Task wants to register as scheduler.
  1998. *
  1999. *    TM_SCHED
  2000. *    call {
  2001. *    }
  2002. *    ret {
  2003. *        int oldschedtid
  2004. *        int tid            // of master pvmd
  2005. *        string name
  2006. *        string arch
  2007. *        int speed
  2008. *        int dsig
  2009. *    }
  2010. */
  2011.  
  2012. int
  2013. tm_sched(tp, mp)
  2014.     struct task *tp;
  2015.     struct pmsg *mp;
  2016. {
  2017.     struct pmsg *mp2;
  2018.     struct hostd *hp;
  2019.  
  2020.     mp2 = replymessage(mp);
  2021.     pkint(mp2, pvmschedtid);
  2022.     hp = hosts->ht_hosts[hosts->ht_master];
  2023.     pkint(mp2, hp->hd_hostpart);
  2024.     pkstr(mp2, hp->hd_name);
  2025.     pkstr(mp2, hp->hd_arch ? hp->hd_arch : "");
  2026.     pkint(mp2, hp->hd_speed);
  2027.     pkint(mp2, hp->hd_dsig);
  2028.     sendmessage(mp2);
  2029.  
  2030.     if (pvmdebmask & PDMSCHED) {
  2031.         pvmlogprintf("tm_sched() old t%x new t%x\n", pvmschedtid, tp->t_tid);
  2032.     }
  2033.     pvmschedtid = tp->t_tid;
  2034.     tp->t_flag |= TF_ISSCHED;
  2035.     return 0;
  2036. }
  2037.  
  2038.  
  2039. /*    tm_tasker()
  2040. *
  2041. *    Task registers as local task starter.
  2042. *
  2043. *    TM_TASKER
  2044. *    call {
  2045. *        int regme    // true to register, false to unregister
  2046. *    }
  2047. *    ret {
  2048. *        int code    // 0 if okay, else error
  2049. *    }
  2050. */
  2051.  
  2052. int
  2053. tm_tasker(tp, mp)
  2054.     struct task *tp;
  2055.     struct pmsg *mp;
  2056. {
  2057.     int regme;
  2058.     struct pmsg *mp2;
  2059.  
  2060.     if (upkint(mp, ®me)) {
  2061.         pvmlogerror("tm_tasker() bad msg format\n");
  2062.         return 0;
  2063.     }
  2064.     mp2 = replymessage(mp);
  2065.  
  2066.     if (regme) {
  2067.         if (taskertid) {
  2068.             pkint(mp2, PvmAlready);
  2069.  
  2070.         } else {
  2071.             taskertid = tp->t_tid;
  2072.             tp->t_flag |= TF_ISTASKER;
  2073.             if (pvmdebmask & PDMTASK) {
  2074.                 pvmlogprintf("tm_tasker() register t%x \n", tp->t_tid);
  2075.             }
  2076.             pkint(mp2, 0);
  2077.         }
  2078.  
  2079.     } else {
  2080.         if (taskertid == tp->t_tid) {
  2081.             taskertid = 0;
  2082.             tp->t_flag &= ~TF_ISTASKER;
  2083.             if (pvmdebmask & PDMTASK) {
  2084.                 pvmlogprintf("tm_tasker() unregister t%x \n", tp->t_tid);
  2085.             }
  2086.             pkint(mp2, 0);
  2087.  
  2088.         } else {
  2089.             if (pvmdebmask & PDMTASK) {
  2090.                 pvmlogprintf("tm_tasker() t%x tries to unregister?\n",
  2091.                         tp->t_tid);
  2092.             }
  2093.             pkint(mp2, PvmNoTask);
  2094.         }
  2095.     }
  2096.     sendmessage(mp2);
  2097.     return 0;
  2098. }
  2099.  
  2100.  
  2101. /*    tm_hoster()
  2102. *
  2103. *    Task registers as slave pvmd starter.
  2104. *
  2105. *    TM_HOSTER
  2106. *        int regme    // true to register, false to unregister
  2107. *    call {
  2108. *    }
  2109. *    ret {
  2110. *        int code    // 0 if okay, else error
  2111. *    }
  2112. */
  2113.  
  2114. int
  2115. tm_hoster(tp, mp)
  2116.     struct task *tp;
  2117.     struct pmsg *mp;
  2118. {
  2119.     int regme;
  2120.     struct pmsg *mp2;
  2121.  
  2122.     if (upkint(mp, ®me)) {
  2123.         pvmlogerror("tm_hoster() bad msg format\n");
  2124.         return 0;
  2125.     }
  2126.  
  2127.     mp2 = replymessage(mp);
  2128.  
  2129.     /* always wear 2 condoms, who knows if indices are enough... :) */
  2130.     if (hosts->ht_hosts[hosts->ht_local]->hd_hostpart
  2131.             != hosts->ht_hosts[hosts->ht_master]->hd_hostpart) {
  2132.         pkint(mp2, PvmHostrNMstr);
  2133.         sendmessage(mp2);
  2134.         return 0;
  2135.     }
  2136.  
  2137.     if (regme) {
  2138.         if (hostertid) {
  2139.             pkint(mp2, PvmAlready);
  2140.  
  2141.         } else {
  2142.             hostertid = tp->t_tid;
  2143.             tp->t_flag |= TF_ISHOSTER;
  2144.             if (pvmdebmask & PDMSTARTUP) {
  2145.                 pvmlogprintf("tm_hoster() register t%x \n", tp->t_tid);
  2146.             }
  2147.             pkint(mp2, 0);
  2148.         }
  2149.  
  2150.     } else {
  2151.         if (hostertid == tp->t_tid) {
  2152.             hostertid = 0;
  2153.             tp->t_flag &= ~TF_ISHOSTER;
  2154.             if (pvmdebmask & PDMSTARTUP) {
  2155.                 pvmlogprintf("tm_hoster() unregister t%x \n", tp->t_tid);
  2156.             }
  2157.             pkint(mp2, 0);
  2158.  
  2159.         } else {
  2160.             if (pvmdebmask & PDMSTARTUP) {
  2161.                 pvmlogprintf("tm_hoster() t%x tries to unregister?\n",
  2162.                         tp->t_tid);
  2163.             }
  2164.             pkint(mp2, PvmNoTask);
  2165.         }
  2166.     }
  2167.  
  2168.     sendmessage(mp2);
  2169.     return 0;
  2170. }
  2171.  
  2172.  
  2173. /*    tm_tracer()
  2174. *
  2175. *    Task registers as task trace collector.
  2176. *
  2177. *    TM_TRACER
  2178. *    call {
  2179. *        int regme        // true to register, false to unregister
  2180. *        int tctx        // if regme true, message ctxt for trace events
  2181. *        int ttag        // if regme true, message tag for trace events
  2182. *        int octx        // if regme true, message ctxt for output events
  2183. *        int otag        // if regme true, message tag for output events
  2184. *        Pvmtmask tmask    // if regme true, trace mask for tasks
  2185. *        int tbuf        // if regme true, trace buffer size for tasks
  2186. *        int topt        // if regme true, trace options for tasks
  2187. *    }
  2188. *    ret {
  2189. *        int code    // 0 if okay, else error
  2190. *    }
  2191. */
  2192.  
  2193. int
  2194. tm_tracer(tp, mp)
  2195.     struct task *tp;
  2196.     struct pmsg *mp;
  2197. {
  2198.     int regme;
  2199.     int tctx;
  2200.     int ttag;
  2201.     int octx;
  2202.     int otag;
  2203.     Pvmtmask tmask;
  2204.     int tbuf;
  2205.     int topt;
  2206.     struct pmsg *mp2;
  2207.     struct pmsg *mpd;
  2208.     int slconf;
  2209.     int hh;
  2210.     struct hostd *hp;
  2211.     char buf[512];
  2212.  
  2213.     if (upkint(mp, ®me)) {
  2214.         pvmlogerror("tm_tracer() bad msg format\n");
  2215.         return 0;
  2216.     }
  2217.  
  2218.     mp2 = replymessage(mp);
  2219.  
  2220.     slconf = 0;
  2221.  
  2222.     if (regme) {
  2223.         if (pvmtracer.trctid) {
  2224.             pkint(mp2, PvmAlready);
  2225.  
  2226.         } else {
  2227.             tp->t_flag |= TF_ISTRACER;
  2228.             upkint(mp, &tctx);
  2229.             upkint(mp, &ttag);
  2230.             upkint(mp, &octx);
  2231.             upkint(mp, &otag);
  2232.             upkstr(mp, tmask, TEV_MASK_LENGTH);
  2233.             upkint(mp, &tbuf);
  2234.             upkint(mp, &topt);
  2235.             pvmtracer.trctid = tp->t_tid;
  2236.             pvmtracer.trcctx = tctx;
  2237.             pvmtracer.trctag = ttag;
  2238.             pvmtracer.outtid = tp->t_tid;
  2239.             pvmtracer.outctx = octx;
  2240.             pvmtracer.outtag = otag;
  2241.             BCOPY(tmask,pvmtracer.tmask,TEV_MASK_LENGTH);
  2242.             pvmtracer.trcbuf = tbuf;
  2243.             pvmtracer.trcopt = topt;
  2244.             slconf++;
  2245.             if (pvmdebmask & PDMTRACE) {
  2246.                 pvmlogprintf("tm_tracer() register t%x \n", tp->t_tid);
  2247.             }
  2248.             pkint(mp2, 0);
  2249.         }
  2250.  
  2251.     } else {
  2252.         if (pvmtracer.trctid == tp->t_tid) {
  2253.             tp->t_flag &= ~TF_ISTRACER;
  2254.             pvmtracer.trctid = 0;
  2255.             pvmtracer.trcctx = 0;
  2256.             pvmtracer.trctag = 0;
  2257.             pvmtracer.outtid = 0;
  2258.             pvmtracer.outctx = 0;
  2259.             pvmtracer.outtag = 0;
  2260.             TEV_MASK_INIT(pvmtracer.tmask);
  2261.             pvmtracer.trcbuf = 0;
  2262.             pvmtracer.trcopt = 0;
  2263.             slconf++;
  2264.             if (pvmdebmask & PDMTRACE) {
  2265.                 pvmlogprintf("tm_tracer() unregister t%x \n",
  2266.                     tp->t_tid);
  2267.             }
  2268.             pkint(mp2, 0);
  2269.  
  2270.         } else {
  2271.             if (pvmdebmask & PDMTRACE) {
  2272.                 pvmlogprintf("tm_tracer() t%x tries to unregister?\n",
  2273.                         tp->t_tid);
  2274.             }
  2275.             pkint(mp2, PvmNoTask);
  2276.         }
  2277.     }
  2278.  
  2279.     /* Update slave pvmds */
  2280.     if ( slconf ) {
  2281.         for (hh = hosts->ht_last; hh > 0; hh--) {
  2282.             if (hp = hosts->ht_hosts[hh]) {
  2283.                 mpd = mesg_new(0);
  2284.                 mpd->m_tag = DM_SLCONF;
  2285.                 mpd->m_dst = hp->hd_hostpart | TIDPVMD;
  2286.                 pkint(mpd, DM_SLCONF_TRACE);
  2287.                 sprintf(buf, "%x %d %d %x %d %d %d %d %s",
  2288.                     pvmtracer.trctid, pvmtracer.trcctx,
  2289.                         pvmtracer.trctag,
  2290.                     pvmtracer.outtid, pvmtracer.outctx,
  2291.                         pvmtracer.outtag,
  2292.                     pvmtracer.trcbuf, pvmtracer.trcopt,
  2293.                     pvmtracer.tmask);
  2294.                 pkstr(mpd, buf);
  2295.                 sendmessage(mpd);
  2296.             }
  2297.         }
  2298.     }
  2299.  
  2300.     /* Send response to requesting task */
  2301.     sendmessage(mp2);
  2302.  
  2303.     return 0;
  2304. }
  2305.  
  2306.  
  2307. /*    tm_hostsync()
  2308. *
  2309. *    Task wants clock sample from host.
  2310. *
  2311. *    TM_HOSTSYNC
  2312. *    call {
  2313. *        int where    // pvmd tid
  2314. *    }
  2315. *    ret {
  2316. *        int status    // 0 or error code
  2317. *        int sec        // time of day clock
  2318. *        int usec
  2319. *    }
  2320. */
  2321.  
  2322. int
  2323. tm_hostsync(tp, mp)
  2324.     struct task *tp;
  2325.     struct pmsg *mp;
  2326. {
  2327.     int where;
  2328.     struct hostd *hp;
  2329.     struct pmsg *mp2;
  2330.     struct waitc *wp;
  2331.  
  2332.     if (upkuint(mp, &where)) {
  2333.         pvmlogerror("tm_hostsync() bad msg format\n");
  2334.         return 0;
  2335.     }
  2336.  
  2337.     mp2 = replymessage(mp);
  2338.  
  2339.     if (!(hp = tidtohost(hosts, where))) {
  2340.         pkint(mp2, PvmNoHost);
  2341.         sendmessage(mp2);
  2342.         return 0;
  2343.     }
  2344.  
  2345.     wp = wait_new(WT_HOSTSYNC);
  2346.     wp->wa_tid = mp->m_src;
  2347.     wp->wa_on = hp->hd_hostpart;
  2348.     wp->wa_mesg = mp2;
  2349.  
  2350.     mp2 = mesg_new(0);
  2351.     mp2->m_dst = where | TIDPVMD;
  2352.     mp2->m_tag = DM_HOSTSYNC;
  2353.     mp2->m_wid = wp->wa_wid;
  2354.  
  2355.     sendmessage(mp2);
  2356.     return 0;
  2357. }
  2358.  
  2359.  
  2360. /*    tm_setopt()
  2361. *
  2362. *    Set task parameters
  2363. *
  2364. *    TM_SETOPT
  2365. *    call {
  2366. *        {
  2367. *            int what        // which option
  2368. *            string value    // option value
  2369. *        } []                // implied
  2370. *    }
  2371. *    ret {
  2372. */
  2373.  
  2374. int
  2375. tm_setopt(tp, mp)
  2376.     struct task *tp;
  2377.     struct pmsg *mp;
  2378. {
  2379.     int what;
  2380.     char *val;
  2381.     int x;
  2382.  
  2383.     while (!upkint(mp, &what) && !upkstralloc(mp, &val)) {
  2384.         switch (what) {
  2385.  
  2386.         case TS_OUTTID:
  2387.             x = pvmxtoi(val);
  2388.             change_output(tp, x, tp->t_outctx, tp->t_outtag);
  2389.             break;
  2390.  
  2391.         case TS_OUTCTX:
  2392.             x = pvmxtoi(val);
  2393.             change_output(tp, tp->t_outtid, x, tp->t_outtag);
  2394.             break;
  2395.  
  2396.         case TS_OUTTAG:
  2397.             x = pvmxtoi(val);
  2398.             change_output(tp, tp->t_outtid, tp->t_outctx, x);
  2399.             break;
  2400.  
  2401.         case TS_TRCTID:
  2402.             x = pvmxtoi(val);
  2403.             change_trace(tp, x, tp->t_trcctx, tp->t_trctag);
  2404.             break;
  2405.  
  2406.         case TS_TRCCTX:
  2407.             x = pvmxtoi(val);
  2408.             change_trace(tp, tp->t_trctid, x, tp->t_trctag);
  2409.             break;
  2410.  
  2411.         case TS_TRCTAG:
  2412.             x = pvmxtoi(val);
  2413.             change_trace(tp, tp->t_trctid, tp->t_trcctx, x);
  2414.             break;
  2415.  
  2416.         default:
  2417.             pvmlogprintf("tm_setopt() ? option %d val <%s>\n", what, val);
  2418.             break;
  2419.         }
  2420.         if (val)
  2421.             PVM_FREE(val);
  2422.     }
  2423.     mp = replymessage(mp);
  2424.     sendmessage(mp);
  2425.     return 0;
  2426. }
  2427.  
  2428.  
  2429. /*    change_output()
  2430. *
  2431. *    Task sets its output sink parameters.
  2432. *    If new values are different we have to send close and open
  2433. *    messages, because the collector won't know what's going on.
  2434. */
  2435.  
  2436. int
  2437. change_output(tp, outtid, outctx, outtag)
  2438.     struct task *tp;
  2439.     int outtid, outctx, outtag;
  2440. {
  2441.     struct pmsg *mp;
  2442.  
  2443.     if (tp->t_outtid != outtid
  2444.     || tp->t_outctx != outctx
  2445.     || tp->t_outtag != outtag) {
  2446.         if (tp->t_outtid > 0) {
  2447.             mp = mesg_new(0);
  2448.             mp->m_dst = tp->t_outtid;
  2449.             mp->m_ctx = tp->t_outctx;
  2450.             mp->m_tag = tp->t_outtag;
  2451.             pkint(mp, tp->t_tid);
  2452.             pkint(mp, 0);
  2453.             sendmessage(mp);
  2454.         }
  2455.         if (pvmdebmask & PDMTASK) {
  2456.             pvmlogprintf("t%x changes output from <t%x %d %d> to <t%x %d %d>\n",
  2457.                     tp->t_tid,
  2458.                     tp->t_outtid, tp->t_outctx, tp->t_outtag,
  2459.                     outtid, outctx, outtag);
  2460.         }
  2461.         tp->t_outtid = outtid;
  2462.         tp->t_outctx = outctx;
  2463.         tp->t_outtag = outtag;
  2464.         if (tp->t_outtid > 0) {
  2465.             mp = mesg_new(0);
  2466.             mp->m_dst = tp->t_outtid;
  2467.             mp->m_ctx = tp->t_outctx;
  2468.             mp->m_tag = tp->t_outtag;
  2469.             pkint(mp, tp->t_tid);
  2470.             pkint(mp, -1);
  2471.             pkint(mp, tp->t_ptid);
  2472.             sendmessage(mp);
  2473.  
  2474.             mp = mesg_new(0);
  2475.             mp->m_dst = tp->t_outtid;
  2476.             mp->m_ctx = tp->t_outctx;
  2477.             mp->m_tag = tp->t_outtag;
  2478.             pkint(mp, tp->t_tid);
  2479.             pkint(mp, -2);
  2480.             pkint(mp, tp->t_ptid);
  2481.             sendmessage(mp);
  2482.         }
  2483.     }
  2484.     return 0;
  2485. }
  2486.  
  2487.  
  2488. /*    tm_getopt()
  2489. *
  2490. *    Connect message for shared memory apps to get trace & output parameters.
  2491. *    XXX hack, will be merged into something else in v3.4.
  2492. *
  2493. *    TM_GETOPT
  2494. *    call { }
  2495. *    ret {
  2496. *        int tid                // task tid
  2497. *        int ptid            // parent tid
  2498. *        int outtid            // output dst
  2499. *        int outctx
  2500. *        int outtag
  2501. *        int trctid            // trace dst
  2502. *        int trcctx
  2503. *        int trctag
  2504. *        int udpmax
  2505. *        int nativecode
  2506. *        string inaddr
  2507. *        int schedtid        // scheduler tid
  2508. *    }
  2509. */
  2510.  
  2511. int
  2512. tm_getopt(tp, mp)
  2513.     struct task *tp;
  2514.     struct pmsg *mp;
  2515. {
  2516.     mp = replymessage(mp);
  2517.     pkint(mp, tp->t_tid);
  2518.     pkint(mp, tp->t_ptid);
  2519.     pkint(mp, tp->t_outtid);
  2520.     pkint(mp, tp->t_outctx);
  2521.     pkint(mp, tp->t_outtag);
  2522.     pkint(mp, tp->t_trctid);
  2523.     pkint(mp, tp->t_trcctx);
  2524.     pkint(mp, tp->t_trctag);
  2525.     pkint(mp, pvmudpmtu);
  2526.     pkint(mp, pvmmydsig);
  2527.     pkstr(mp, inadport_hex(&(hosts->ht_hosts[hosts->ht_local]->hd_sad)));
  2528.     pkint(mp, pvmschedtid);
  2529.     mp->m_flag |= MM_PRIO;  /* set priority handling for this message */
  2530.     sendmessage(mp);
  2531.  
  2532. #if defined(SHMEM)
  2533.  
  2534.     /* now change connection to TF_SHMCONN and try send packets that have
  2535.         gathered in this tasks sendq */
  2536.     tp->t_flag &= ~TF_PRESHMCONN;  
  2537.     tp->t_flag |= TF_SHMCONN;
  2538.     
  2539.     shm_wrt_pkts(tp); /* write  any waiting packets */
  2540.     
  2541. #endif
  2542.     return 0;
  2543. }
  2544.  
  2545.  
  2546. /*    change_output()
  2547. *
  2548. *    Task sets its trace sink parameters.
  2549. *    If new values are different we have to send close and open
  2550. *    messages, because the collector won't know what's going on.
  2551. */
  2552.  
  2553. int
  2554. change_trace(tp, trctid, trcctx, trctag)
  2555.     struct task *tp;
  2556.     int trctid, trcctx, trctag;
  2557. {
  2558.     struct pmsg *mp;
  2559.  
  2560.     if (tp->t_trctid != trctid
  2561.             || tp->t_trcctx != trcctx
  2562.             || tp->t_trctag != trctag) {
  2563.         if (tp->t_trctid > 0) {
  2564.             tev_send_endtask(
  2565.                 tp->t_trctid, tp->t_trcctx, tp->t_trctag,
  2566.                 tp->t_tid, tp->t_status,
  2567.                 tp->t_utime.tv_sec, tp->t_utime.tv_usec,
  2568.                 tp->t_stime.tv_sec, tp->t_stime.tv_usec );
  2569.         }
  2570.         if (pvmdebmask & PDMTASK) {
  2571.             pvmlogprintf( "t%x changes trace from <t%x %d %d> to <t%x %d %d>\n",
  2572.                     tp->t_tid,
  2573.                     tp->t_trctid, tp->t_trcctx, tp->t_trctag,
  2574.                     trctid, trcctx, trctag);
  2575.         }
  2576.         tp->t_trctid = trctid;
  2577.         tp->t_trcctx = trcctx;
  2578.         tp->t_trctag = trctag;
  2579.         if (tp->t_trctid > 0) {
  2580.             tev_send_spntask(
  2581.                 tp->t_trctid, tp->t_trcctx, tp->t_trctag,
  2582.                 tp->t_tid, tp->t_ptid );
  2583.             tev_send_newtask(
  2584.                 tp->t_trctid, tp->t_trcctx, tp->t_trctag,
  2585.                 tp->t_tid, tp->t_ptid, 0 /* XXX lie */,
  2586.                 tp->t_a_out ? tp->t_a_out : "" );
  2587.         }
  2588.     }
  2589.     return 0;
  2590. }
  2591.  
  2592.  
  2593. /*    tm_context()
  2594. *
  2595. *    Assign task a communication context, or free one in use
  2596. *
  2597. *    TM_CONTEXT
  2598. *    call {
  2599. *        int cid            // to free, or zero if requesting one
  2600. *    }
  2601. *    ret {
  2602. *        int cid            // new cid or status
  2603. *    }
  2604. */
  2605.  
  2606. int
  2607. tm_context(tp, mp)
  2608.     struct task *tp;
  2609.     struct pmsg *mp;
  2610. {
  2611.     struct pmsg *mp2;
  2612.     struct ccon *cp;
  2613.     int cid;
  2614.     int cc;
  2615.  
  2616.     mp2 = replymessage(mp);
  2617.     if (upkuint(mp, &cid)) {
  2618.         cc = PvmBadParam;
  2619.  
  2620.     } else {
  2621.         if (cid == 0) {
  2622.             if (cp = ccon_new(tp))
  2623.                 cc = cp->c_cid;
  2624.             else
  2625.                 cc = PvmOutOfRes;
  2626.  
  2627.         } else {
  2628.             cc = PvmNotFound;
  2629.             if (tp->t_ccs) {
  2630.                 FORLIST (cp, tp->t_ccs, c_peer) {
  2631.                     if (cp->c_cid == cid) {
  2632.                         LISTDELETE(cp, c_link, c_rlink);
  2633.                         LISTDELETE(cp, c_peer, c_rpeer);
  2634.                         PVM_FREE(cp);
  2635.                         cc = 0;
  2636.                         break;
  2637.                     }
  2638.                 }
  2639.             }
  2640.         }
  2641.     }
  2642.     pkint(mp2, cc);
  2643.     sendmessage(mp2);
  2644.     return 0;
  2645. }
  2646.  
  2647.  
  2648. /*    tm_shmconn()
  2649.  *
  2650.  *    Task connecting to pvmd under the shmem system.
  2651.  *    This is used to tie the task to the pvmd socket into the correct
  2652.  *    task struct.  This socket is a one-way only socket that is used
  2653.  *    by the task to kick the daemon when the task has put a message
  2654.  *    for it in its shared memory inbox segment.  The socket is also
  2655.  *    used to catch when the task dies....
  2656.  *    
  2657.  *    There is no d-auth file checking.
  2658.  *    Only data passed is the task's pid so we can match it with our
  2659.  *    own table.
  2660.  *
  2661.  *    TM_SHMCONN()
  2662.  *    call {
  2663.  *        int unixpid            // real pid
  2664.  *    }
  2665.  *    ret {
  2666.  *    }
  2667.  */
  2668.  
  2669. int
  2670. tm_shmconn(tp, mp)
  2671.     struct task *tp;
  2672.     struct pmsg *mp;    /* remember no return message */
  2673. {
  2674.     int tid;            
  2675.     int pid;                        /* real pid of task */
  2676.     int ppid;                        /* probable pid */
  2677.     struct task *tp2;                /* to search for real context */
  2678.     struct pmsg *mp2;
  2679.     int cc;
  2680.     char c;
  2681.  
  2682.     if ( upkint( mp, &ppid ) ) {
  2683.         pvmlogerror(
  2684.                 "tm_shmconn() bad msg format. Missing Unix pid??\n" );
  2685.         goto bail;
  2686.     }
  2687.  
  2688. #ifndef    SHMEM
  2689.     if ( 1 ) {
  2690.         pvmlogerror( "tm_shmconn() shmem conn on non shmem sys? " );
  2691.         pvmlogerror( "Bit bucket...\n" );
  2692.         goto bail;
  2693.     }
  2694. #endif
  2695.     
  2696.     /*
  2697.     *    Task should already have a correct task struct.
  2698.     *    Because TM_SHMCONN is passed after the shmem connect phase
  2699.     *    in pvmbeatask() in lpvmshmem.c
  2700.     */
  2701.  
  2702.     if ( tp2 = task_findpid( ppid ) )
  2703.     {
  2704.         if ( pvmdebmask & PDMTASK ) {
  2705.             pvmlogprintf(
  2706.                     "tm_shmconn() reconnect task t%x via sockets\n",
  2707.                     tp2->t_tid);
  2708.         }
  2709.         /* tp->t_sched = tp2->t_sched; */
  2710.     }
  2711.     else
  2712.     {
  2713.         pvmlogerror( "tm_shmconn() conn from non shmem connd task?\n");
  2714.         goto bail;        
  2715.     }
  2716.  
  2717.     /* 
  2718.      * tp2 is now the real task.... 
  2719.      * So we now update it with the correct socket descripter and then
  2720.      * mark the shadow one as dead.
  2721.      *
  2722.      */
  2723.  
  2724.     tp2->t_sock = tp->t_sock;
  2725.  
  2726.     tp->t_sock = -1;    /* tp will be freed by loclinput() */
  2727.     tp->t_rxp = 0;
  2728.     tp->t_flag |= TF_CLOSE; /* stop work() complaining - dead socket? */
  2729.  
  2730.     /*
  2731.      *    kick it in the butt; it's ready to go
  2732.      */
  2733.  
  2734.     /* We are happy to mark it as a shared memory connected process */
  2735.     /* i.e. please use shmem (mpp_output) not my socket to talk to me */
  2736.  
  2737.     /* the PRESHMCONN flag indicates that messages with MM_PRIO can be
  2738.         sent over shared memory, but no others.  tm_getopt will
  2739.         set the flag to SHMCONN
  2740.     */
  2741.     tp2->t_flag |= TF_PRESHMCONN;
  2742.  
  2743.     return 0;
  2744.  
  2745. bail:
  2746.     /* i.e. kill it! */
  2747.     tp->t_sock = -1;    /* tp will be freed by loclinput() */
  2748.     tp->t_rxp = 0;
  2749.     tp->t_flag |= TF_CLOSE;
  2750.     return 0;
  2751. }
  2752.  
  2753.